mirror of
https://github.com/home-assistant/core.git
synced 2026-01-09 00:58:32 +01:00
Compare commits
133 Commits
otbr_user_
...
2023.1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b297b78086 | ||
|
|
4bdf87d383 | ||
|
|
e47364f34d | ||
|
|
fe7d32dc5d | ||
|
|
62a003a053 | ||
|
|
b5d1421dfd | ||
|
|
ebab2bd0f9 | ||
|
|
e7babb4266 | ||
|
|
1a042c2dad | ||
|
|
731ca046f6 | ||
|
|
c844276e95 | ||
|
|
9f9cdb62eb | ||
|
|
c73830439f | ||
|
|
940b5d62b4 | ||
|
|
b3454bfd9c | ||
|
|
834847988d | ||
|
|
caf15534bb | ||
|
|
10cb2e31c4 | ||
|
|
85c9f9facf | ||
|
|
5ff7b3bb1a | ||
|
|
e5ba423d6d | ||
|
|
b30d4ef7cf | ||
|
|
00e563f1b8 | ||
|
|
cf06f3b81d | ||
|
|
a781fcca86 | ||
|
|
764550f2e1 | ||
|
|
7396bcc585 | ||
|
|
7e6b087773 | ||
|
|
71ce7373a3 | ||
|
|
33bb9c230b | ||
|
|
f0f2c12d91 | ||
|
|
2840821594 | ||
|
|
edfd83c3a7 | ||
|
|
ee88f34a91 | ||
|
|
fa4c250001 | ||
|
|
59d6f827c3 | ||
|
|
26ea02aa8f | ||
|
|
d73b86132b | ||
|
|
8034faadca | ||
|
|
3c2b7c0d69 | ||
|
|
563ad02c65 | ||
|
|
fe89b663e7 | ||
|
|
dcd07d3135 | ||
|
|
8bf2299407 | ||
|
|
9c689d757c | ||
|
|
4e4fc1767f | ||
|
|
cc3c5772c5 | ||
|
|
6ba6991ecd | ||
|
|
d52d068469 | ||
|
|
09b3611a63 | ||
|
|
ab2f05d3e9 | ||
|
|
90ac0c870f | ||
|
|
0fd113db59 | ||
|
|
1b43323f5e | ||
|
|
6108e581b1 | ||
|
|
c8c68f05ec | ||
|
|
b80467dc58 | ||
|
|
6e9f0eca03 | ||
|
|
cc6a2f0338 | ||
|
|
6ebf2ec9ec | ||
|
|
9ecee11af6 | ||
|
|
9a1669103b | ||
|
|
368ea0586d | ||
|
|
4a7db6ee71 | ||
|
|
a10b9572c7 | ||
|
|
0b47bf1f0b | ||
|
|
5f4d286556 | ||
|
|
b23ab3c65a | ||
|
|
7c199b36f8 | ||
|
|
d4e55ee030 | ||
|
|
f3ec82543e | ||
|
|
4013d4c48d | ||
|
|
93ac908776 | ||
|
|
2ad1a53038 | ||
|
|
3ba59fbebe | ||
|
|
f3fab5c1f5 | ||
|
|
2d120cb6ba | ||
|
|
ad782166c7 | ||
|
|
bc9202cf02 | ||
|
|
0d385d3b67 | ||
|
|
76fa24aba1 | ||
|
|
95ae37cd87 | ||
|
|
bc1d22f4ec | ||
|
|
67e1872ab6 | ||
|
|
516c2b0cdb | ||
|
|
60f067b68f | ||
|
|
ff76567061 | ||
|
|
93488cfa0f | ||
|
|
9655619667 | ||
|
|
32736b3336 | ||
|
|
c77b78928e | ||
|
|
a7ba242f1f | ||
|
|
043d58d697 | ||
|
|
6408890543 | ||
|
|
c5f7d7ae85 | ||
|
|
7ab27cd9bf | ||
|
|
9932c0cb91 | ||
|
|
565d4f85c1 | ||
|
|
7be60d4569 | ||
|
|
a50622cbfd | ||
|
|
fb41b024c0 | ||
|
|
80ac4c0269 | ||
|
|
0e0677b690 | ||
|
|
50d9e3efe6 | ||
|
|
ca28006d76 | ||
|
|
ac3711e6ab | ||
|
|
5901964bf6 | ||
|
|
b24c40f2df | ||
|
|
2cb7a80f98 | ||
|
|
f05de2b28c | ||
|
|
d9aff9d7b0 | ||
|
|
46e11c2fa8 | ||
|
|
522477d5a4 | ||
|
|
cc2b592221 | ||
|
|
bd86111dd8 | ||
|
|
f0514008fa | ||
|
|
3c8a66abbe | ||
|
|
f1d509be03 | ||
|
|
fbdc7d44bc | ||
|
|
cae386465e | ||
|
|
31847e3a69 | ||
|
|
5787e1506c | ||
|
|
9a29f64128 | ||
|
|
6c0e4a9e8f | ||
|
|
9ce64f8990 | ||
|
|
6ef4086683 | ||
|
|
b146f52317 | ||
|
|
001bd78bcb | ||
|
|
ba4ec8f8c1 | ||
|
|
8aa3a6cc15 | ||
|
|
ed43e1d3a4 | ||
|
|
b7654c0fce | ||
|
|
99f3cfdf8a |
33
.coveragerc
33
.coveragerc
@@ -195,6 +195,9 @@ omit =
|
||||
homeassistant/components/control4/const.py
|
||||
homeassistant/components/control4/director_utils.py
|
||||
homeassistant/components/control4/light.py
|
||||
homeassistant/components/coolmaster/__init__.py
|
||||
homeassistant/components/coolmaster/climate.py
|
||||
homeassistant/components/coolmaster/const.py
|
||||
homeassistant/components/cppm_tracker/device_tracker.py
|
||||
homeassistant/components/crownstone/__init__.py
|
||||
homeassistant/components/crownstone/const.py
|
||||
@@ -230,9 +233,6 @@ omit =
|
||||
homeassistant/components/discord/notify.py
|
||||
homeassistant/components/dlib_face_detect/image_processing.py
|
||||
homeassistant/components/dlib_face_identify/image_processing.py
|
||||
homeassistant/components/dlink/__init__.py
|
||||
homeassistant/components/dlink/data.py
|
||||
homeassistant/components/dlink/entity.py
|
||||
homeassistant/components/dlink/switch.py
|
||||
homeassistant/components/dominos/*
|
||||
homeassistant/components/doods/*
|
||||
@@ -351,8 +351,6 @@ omit =
|
||||
homeassistant/components/esphome/switch.py
|
||||
homeassistant/components/etherscan/sensor.py
|
||||
homeassistant/components/eufy/*
|
||||
homeassistant/components/eufylife_ble/__init__.py
|
||||
homeassistant/components/eufylife_ble/sensor.py
|
||||
homeassistant/components/everlights/light.py
|
||||
homeassistant/components/evohome/*
|
||||
homeassistant/components/ezviz/__init__.py
|
||||
@@ -566,8 +564,6 @@ omit =
|
||||
homeassistant/components/ifttt/const.py
|
||||
homeassistant/components/iglo/light.py
|
||||
homeassistant/components/ihc/*
|
||||
homeassistant/components/imap/__init__.py
|
||||
homeassistant/components/imap/coordinator.py
|
||||
homeassistant/components/imap/sensor.py
|
||||
homeassistant/components/imap_email_content/sensor.py
|
||||
homeassistant/components/incomfort/*
|
||||
@@ -588,7 +584,6 @@ omit =
|
||||
homeassistant/components/intellifire/coordinator.py
|
||||
homeassistant/components/intellifire/entity.py
|
||||
homeassistant/components/intellifire/fan.py
|
||||
homeassistant/components/intellifire/light.py
|
||||
homeassistant/components/intellifire/number.py
|
||||
homeassistant/components/intellifire/sensor.py
|
||||
homeassistant/components/intellifire/switch.py
|
||||
@@ -604,7 +599,6 @@ omit =
|
||||
homeassistant/components/iss/sensor.py
|
||||
homeassistant/components/isy994/__init__.py
|
||||
homeassistant/components/isy994/binary_sensor.py
|
||||
homeassistant/components/isy994/button.py
|
||||
homeassistant/components/isy994/climate.py
|
||||
homeassistant/components/isy994/cover.py
|
||||
homeassistant/components/isy994/entity.py
|
||||
@@ -612,9 +606,6 @@ omit =
|
||||
homeassistant/components/isy994/helpers.py
|
||||
homeassistant/components/isy994/light.py
|
||||
homeassistant/components/isy994/lock.py
|
||||
homeassistant/components/isy994/models.py
|
||||
homeassistant/components/isy994/number.py
|
||||
homeassistant/components/isy994/select.py
|
||||
homeassistant/components/isy994/sensor.py
|
||||
homeassistant/components/isy994/services.py
|
||||
homeassistant/components/isy994/switch.py
|
||||
@@ -682,9 +673,6 @@ omit =
|
||||
homeassistant/components/lcn/helpers.py
|
||||
homeassistant/components/lcn/scene.py
|
||||
homeassistant/components/lcn/services.py
|
||||
homeassistant/components/ld2410_ble/__init__.py
|
||||
homeassistant/components/ld2410_ble/binary_sensor.py
|
||||
homeassistant/components/ld2410_ble/coordinator.py
|
||||
homeassistant/components/led_ble/__init__.py
|
||||
homeassistant/components/led_ble/light.py
|
||||
homeassistant/components/lg_netcast/media_player.py
|
||||
@@ -857,6 +845,7 @@ omit =
|
||||
homeassistant/components/nibe_heatpump/__init__.py
|
||||
homeassistant/components/nibe_heatpump/climate.py
|
||||
homeassistant/components/nibe_heatpump/binary_sensor.py
|
||||
homeassistant/components/nibe_heatpump/button.py
|
||||
homeassistant/components/nibe_heatpump/number.py
|
||||
homeassistant/components/nibe_heatpump/select.py
|
||||
homeassistant/components/nibe_heatpump/sensor.py
|
||||
@@ -881,7 +870,6 @@ omit =
|
||||
homeassistant/components/nuki/binary_sensor.py
|
||||
homeassistant/components/nuki/const.py
|
||||
homeassistant/components/nuki/lock.py
|
||||
homeassistant/components/nuki/sensor.py
|
||||
homeassistant/components/nut/diagnostics.py
|
||||
homeassistant/components/nx584/alarm_control_panel.py
|
||||
homeassistant/components/nzbget/coordinator.py
|
||||
@@ -1073,7 +1061,6 @@ omit =
|
||||
homeassistant/components/rest/switch.py
|
||||
homeassistant/components/rfxtrx/diagnostics.py
|
||||
homeassistant/components/ridwell/__init__.py
|
||||
homeassistant/components/ridwell/entity.py
|
||||
homeassistant/components/ridwell/sensor.py
|
||||
homeassistant/components/ridwell/switch.py
|
||||
homeassistant/components/ring/camera.py
|
||||
@@ -1095,9 +1082,6 @@ omit =
|
||||
homeassistant/components/rova/sensor.py
|
||||
homeassistant/components/rpi_camera/*
|
||||
homeassistant/components/rtorrent/sensor.py
|
||||
homeassistant/components/ruuvi_gateway/__init__.py
|
||||
homeassistant/components/ruuvi_gateway/bluetooth.py
|
||||
homeassistant/components/ruuvi_gateway/coordinator.py
|
||||
homeassistant/components/russound_rio/media_player.py
|
||||
homeassistant/components/russound_rnet/media_player.py
|
||||
homeassistant/components/sabnzbd/__init__.py
|
||||
@@ -1229,10 +1213,6 @@ omit =
|
||||
homeassistant/components/squeezebox/__init__.py
|
||||
homeassistant/components/squeezebox/browse_media.py
|
||||
homeassistant/components/squeezebox/media_player.py
|
||||
homeassistant/components/starlink/binary_sensor.py
|
||||
homeassistant/components/starlink/coordinator.py
|
||||
homeassistant/components/starlink/entity.py
|
||||
homeassistant/components/starlink/sensor.py
|
||||
homeassistant/components/starline/__init__.py
|
||||
homeassistant/components/starline/account.py
|
||||
homeassistant/components/starline/binary_sensor.py
|
||||
@@ -1615,11 +1595,6 @@ omit =
|
||||
homeassistant/components/zerproc/__init__.py
|
||||
homeassistant/components/zerproc/const.py
|
||||
homeassistant/components/zestimate/sensor.py
|
||||
homeassistant/components/zeversolar/__init__.py
|
||||
homeassistant/components/zeversolar/const.py
|
||||
homeassistant/components/zeversolar/coordinator.py
|
||||
homeassistant/components/zeversolar/entity.py
|
||||
homeassistant/components/zeversolar/sensor.py
|
||||
homeassistant/components/zha/api.py
|
||||
homeassistant/components/zha/core/channels/*
|
||||
homeassistant/components/zha/core/const.py
|
||||
|
||||
@@ -45,13 +45,5 @@
|
||||
"!include_dir_merge_list scalar",
|
||||
"!include_dir_merge_named scalar"
|
||||
]
|
||||
},
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/sshd:1": {
|
||||
"version": "latest"
|
||||
},
|
||||
"ghcr.io/devcontainers/features/github-cli:1": {
|
||||
"version": "latest"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
47
.github/workflows/builder.yml
vendored
47
.github/workflows/builder.yml
vendored
@@ -24,12 +24,12 @@ jobs:
|
||||
publish: ${{ steps.version.outputs.publish }}
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
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.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
|
||||
@@ -100,7 +100,7 @@ jobs:
|
||||
arch: ${{ fromJson(needs.init.outputs.architectures) }}
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
|
||||
- name: Download nightly wheels of frontend
|
||||
if: needs.init.outputs.channel == 'dev'
|
||||
@@ -113,20 +113,9 @@ jobs:
|
||||
workflow_conclusion: success
|
||||
name: wheels
|
||||
|
||||
- name: Download nightly wheels of intents
|
||||
if: needs.init.outputs.channel == 'dev'
|
||||
uses: dawidd6/action-download-artifact@v2
|
||||
with:
|
||||
github_token: ${{secrets.GITHUB_TOKEN}}
|
||||
repo: home-assistant/intents
|
||||
branch: main
|
||||
workflow: nightly.yaml
|
||||
workflow_conclusion: success
|
||||
name: package
|
||||
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
if: needs.init.outputs.channel == 'dev'
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
|
||||
@@ -151,24 +140,6 @@ jobs:
|
||||
python -m script.gen_requirements_all
|
||||
fi
|
||||
|
||||
if [[ "$(ls home_assistant_intents*.whl)" =~ ^home_assistant_intents-(.*)-py3-none-any.whl$ ]]; then
|
||||
echo "Found intents wheel, setting version to: ${BASH_REMATCH[1]}"
|
||||
yq \
|
||||
--inplace e -o json \
|
||||
'del(.requirements[] | select(contains("home-assistant-intents")))' \
|
||||
homeassistant/components/conversation/manifest.json
|
||||
|
||||
intents_version="${BASH_REMATCH[1]}" yq \
|
||||
--inplace e -o json \
|
||||
'.requirements += ["home-assistant-intents=="+env(intents_version)]' \
|
||||
homeassistant/components/conversation/manifest.json
|
||||
|
||||
sed -i "s|home-assistant-intents==.*|home-assistant-intents==${BASH_REMATCH[1]}|" \
|
||||
homeassistant/package_constraints.txt
|
||||
|
||||
python -m script.gen_requirements_all
|
||||
fi
|
||||
|
||||
- name: Write meta info file
|
||||
shell: bash
|
||||
run: |
|
||||
@@ -227,7 +198,7 @@ jobs:
|
||||
- yellow
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
|
||||
- name: Set build additional args
|
||||
run: |
|
||||
@@ -270,7 +241,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
|
||||
- name: Initialize git
|
||||
uses: home-assistant/actions/helpers/git-init@master
|
||||
@@ -309,7 +280,7 @@ jobs:
|
||||
- "homeassistant"
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
|
||||
- name: Login to DockerHub
|
||||
if: matrix.registry == 'homeassistant'
|
||||
|
||||
100
.github/workflows/ci.yaml
vendored
100
.github/workflows/ci.yaml
vendored
@@ -22,7 +22,7 @@ on:
|
||||
env:
|
||||
CACHE_VERSION: 3
|
||||
PIP_CACHE_VERSION: 3
|
||||
HA_SHORT_VERSION: 2023.2
|
||||
HA_SHORT_VERSION: 2023.1
|
||||
DEFAULT_PYTHON: 3.9
|
||||
ALL_PYTHON_VERSIONS: "['3.9', '3.10']"
|
||||
PRE_COMMIT_CACHE: ~/.cache/pre-commit
|
||||
@@ -56,7 +56,7 @@ jobs:
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Generate partial Python venv restore key
|
||||
id: generate_python_cache_key
|
||||
run: >-
|
||||
@@ -167,16 +167,16 @@ jobs:
|
||||
- info
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
id: python
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
check-latest: true
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.2.3
|
||||
uses: actions/cache@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@@ -191,7 +191,7 @@ jobs:
|
||||
pip install "$(cat requirements_test.txt | grep pre-commit)"
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache@v3.2.3
|
||||
uses: actions/cache@v3.2.2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||
key: >-
|
||||
@@ -211,16 +211,16 @@ jobs:
|
||||
- pre-commit
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
check-latest: true
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@@ -233,7 +233,7 @@ jobs:
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||
key: >-
|
||||
@@ -265,16 +265,16 @@ jobs:
|
||||
- pre-commit
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
check-latest: true
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@@ -287,7 +287,7 @@ jobs:
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||
key: >-
|
||||
@@ -322,16 +322,16 @@ jobs:
|
||||
- pre-commit
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
check-latest: true
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@@ -344,7 +344,7 @@ jobs:
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||
key: >-
|
||||
@@ -368,16 +368,16 @@ jobs:
|
||||
- pre-commit
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
id: python
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
check-latest: true
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@@ -390,7 +390,7 @@ jobs:
|
||||
exit 1
|
||||
- name: Restore pre-commit environment from cache
|
||||
id: cache-precommit
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||
key: >-
|
||||
@@ -495,10 +495,10 @@ jobs:
|
||||
python-version: ${{ fromJSON(needs.info.outputs.python_versions) }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
id: python
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
check-latest: true
|
||||
@@ -509,7 +509,7 @@ jobs:
|
||||
env.HA_SHORT_VERSION }}-$(date -u '+%Y-%m-%dT%H:%M:%s')" >> $GITHUB_OUTPUT
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache@v3.2.3
|
||||
uses: actions/cache@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@@ -517,7 +517,7 @@ jobs:
|
||||
needs.info.outputs.python_cache_key }}
|
||||
- name: Restore pip wheel cache
|
||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
||||
uses: actions/cache@v3.2.3
|
||||
uses: actions/cache@v3.2.2
|
||||
with:
|
||||
path: ${{ env.PIP_CACHE }}
|
||||
key: >-
|
||||
@@ -559,16 +559,16 @@ jobs:
|
||||
- base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
id: python
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
check-latest: true
|
||||
- name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@@ -592,16 +592,16 @@ jobs:
|
||||
- base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
id: python
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
check-latest: true
|
||||
- name: Restore base Python virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@@ -626,16 +626,16 @@ jobs:
|
||||
- base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
id: python
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
check-latest: true
|
||||
- name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@@ -671,16 +671,16 @@ jobs:
|
||||
- base
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
id: python
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
check-latest: true
|
||||
- name: Restore full Python ${{ env.DEFAULT_PYTHON }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@@ -720,16 +720,16 @@ jobs:
|
||||
name: Run pip check ${{ matrix.python-version }}
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
id: python
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
check-latest: true
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: >-
|
||||
@@ -775,16 +775,16 @@ jobs:
|
||||
bluez \
|
||||
ffmpeg
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
id: python
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
check-latest: true
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
@@ -852,7 +852,7 @@ jobs:
|
||||
-p no:sugar \
|
||||
tests/components/${{ matrix.group }}
|
||||
- name: Upload coverage artifact
|
||||
uses: actions/upload-artifact@v3.1.2
|
||||
uses: actions/upload-artifact@v3.1.1
|
||||
with:
|
||||
name: coverage-${{ matrix.python-version }}-${{ matrix.group }}
|
||||
path: coverage.xml
|
||||
@@ -898,16 +898,16 @@ jobs:
|
||||
ffmpeg \
|
||||
libmariadb-dev-compat
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
id: python
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
check-latest: true
|
||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||
id: cache-venv
|
||||
uses: actions/cache/restore@v3.2.3
|
||||
uses: actions/cache/restore@v3.2.2
|
||||
with:
|
||||
path: venv
|
||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||
@@ -954,7 +954,7 @@ jobs:
|
||||
--dburl=mysql://root:password@127.0.0.1/homeassistant-test \
|
||||
tests/components/recorder
|
||||
- name: Upload coverage artifact
|
||||
uses: actions/upload-artifact@v3.1.2
|
||||
uses: actions/upload-artifact@v3.1.1
|
||||
with:
|
||||
name: coverage-${{ matrix.python-version }}-mariadb
|
||||
path: coverage.xml
|
||||
@@ -970,7 +970,7 @@ jobs:
|
||||
- pytest
|
||||
steps:
|
||||
- name: Check out code from GitHub
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
- name: Download all coverage artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
- name: Upload coverage to Codecov (full coverage)
|
||||
|
||||
141
.github/workflows/stale.yml
vendored
141
.github/workflows/stale.yml
vendored
@@ -11,88 +11,83 @@ jobs:
|
||||
if: github.repository_owner == 'home-assistant'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
# The 90 day stale policy for PRs
|
||||
# The 90 day stale policy
|
||||
# Used for:
|
||||
# - PRs
|
||||
# - Issues & PRs
|
||||
# - No PRs marked as no-stale
|
||||
# - No issues (-1)
|
||||
- name: 90 days stale PRs policy
|
||||
# - No issues marked as no-stale or help-wanted
|
||||
- name: 90 days stale issues & PRs policy
|
||||
uses: actions/stale@v7.0.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 90
|
||||
days-before-close: 7
|
||||
days-before-issue-stale: -1
|
||||
days-before-issue-close: -1
|
||||
operations-per-run: 150
|
||||
remove-stale-when-updated: true
|
||||
stale-pr-label: "stale"
|
||||
exempt-pr-labels: "no-stale"
|
||||
stale-pr-message: >
|
||||
There hasn't been any activity on this pull request recently. This
|
||||
pull request has been automatically marked as stale because of that
|
||||
and will be closed if no further activity occurs within 7 days.
|
||||
|
||||
Thank you for your contributions.
|
||||
|
||||
# Generate a token for the GitHub App, we use this method to avoid
|
||||
# hitting API limits for our GitHub actions + have a higher rate limit.
|
||||
# This is only used for issues.
|
||||
- name: Generate app token
|
||||
id: token
|
||||
# Pinned to a specific version of the action for security reasons
|
||||
# v1.7.0
|
||||
uses: tibdex/github-app-token@021a2405c7f990db57f5eae5397423dcc554159c
|
||||
with:
|
||||
app_id: ${{ secrets.ISSUE_TRIAGE_APP_ID }}
|
||||
private_key: ${{ secrets.ISSUE_TRIAGE_APP_PEM }}
|
||||
|
||||
# The 90 day stale policy for issues
|
||||
# Used for:
|
||||
# - Issues
|
||||
# - No issues marked as no-stale or help-wanted
|
||||
# - No PRs (-1)
|
||||
- name: 90 days stale issues
|
||||
uses: actions/stale@v7.0.0
|
||||
with:
|
||||
repo-token: ${{ steps.token.outputs.token }}
|
||||
days-before-stale: 90
|
||||
days-before-close: 7
|
||||
days-before-pr-stale: -1
|
||||
days-before-pr-close: -1
|
||||
operations-per-run: 250
|
||||
remove-stale-when-updated: true
|
||||
stale-issue-label: "stale"
|
||||
exempt-issue-labels: "no-stale,help-wanted,needs-more-information"
|
||||
stale-issue-message: >
|
||||
There hasn't been any activity on this issue recently. Due to the
|
||||
high number of incoming GitHub notifications, we have to clean some
|
||||
of the old issues, as many of them have already been resolved with
|
||||
the latest updates.
|
||||
|
||||
Please make sure to update to the latest Home Assistant version and
|
||||
check if that solves the issue. Let us know if that works for you by
|
||||
adding a comment 👍
|
||||
|
||||
This issue has now been marked as stale and will be closed if no
|
||||
further activity occurs. Thank you for your contributions.
|
||||
|
||||
# The 30 day stale policy for issues
|
||||
# Used for:
|
||||
# - Issues that are pending more information (incomplete issues)
|
||||
# - No Issues marked as no-stale or help-wanted
|
||||
# - No PRs (-1)
|
||||
- name: Needs more information stale issues policy
|
||||
uses: actions/stale@v7.0.0
|
||||
with:
|
||||
repo-token: ${{ steps.token.outputs.token }}
|
||||
only-labels: "needs-more-information"
|
||||
days-before-stale: 14
|
||||
days-before-close: 7
|
||||
days-before-pr-stale: -1
|
||||
days-before-pr-close: -1
|
||||
operations-per-run: 250
|
||||
remove-stale-when-updated: true
|
||||
stale-issue-label: "stale"
|
||||
exempt-issue-labels: "no-stale,help-wanted"
|
||||
stale-issue-message: >
|
||||
There hasn't been any activity on this issue recently. Due to the
|
||||
high number of incoming GitHub notifications, we have to clean some
|
||||
of the old issues, as many of them have already been resolved with
|
||||
the latest updates.
|
||||
|
||||
Please make sure to update to the latest Home Assistant version and
|
||||
check if that solves the issue. Let us know if that works for you by
|
||||
adding a comment 👍
|
||||
|
||||
This issue has now been marked as stale and will be closed if no
|
||||
further activity occurs. Thank you for your contributions.
|
||||
|
||||
stale-pr-label: "stale"
|
||||
exempt-pr-labels: "no-stale"
|
||||
stale-pr-message: >
|
||||
There hasn't been any activity on this pull request recently. This
|
||||
pull request has been automatically marked as stale because of that
|
||||
and will be closed if no further activity occurs within 7 days.
|
||||
|
||||
Thank you for your contributions.
|
||||
|
||||
# The 30 day stale policy for PRS
|
||||
# Used for:
|
||||
# - PRs
|
||||
# - No PRs marked as no-stale or new-integrations
|
||||
# - No issues (-1)
|
||||
- name: 30 days stale PRs policy
|
||||
uses: actions/stale@v7.0.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 30
|
||||
days-before-close: 7
|
||||
days-before-issue-close: -1
|
||||
operations-per-run: 50
|
||||
remove-stale-when-updated: true
|
||||
stale-pr-label: "stale"
|
||||
# Exempt new integrations, these often take more time.
|
||||
# They will automatically be handled by the 90 day version above.
|
||||
exempt-pr-labels: "no-stale,new-integration"
|
||||
stale-pr-message: >
|
||||
There hasn't been any activity on this pull request recently. This
|
||||
pull request has been automatically marked as stale because of that
|
||||
and will be closed if no further activity occurs within 7 days.
|
||||
|
||||
Thank you for your contributions.
|
||||
|
||||
# The 30 day stale policy for issues
|
||||
# Used for:
|
||||
# - Issues that are pending more information (incomplete issues)
|
||||
# - No Issues marked as no-stale or help-wanted
|
||||
# - No PRs (-1)
|
||||
- name: Needs more information stale issues policy
|
||||
uses: actions/stale@v7.0.0
|
||||
with:
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
only-labels: "needs-more-information"
|
||||
days-before-stale: 14
|
||||
days-before-close: 7
|
||||
days-before-pr-close: -1
|
||||
operations-per-run: 50
|
||||
remove-stale-when-updated: true
|
||||
stale-issue-label: "stale"
|
||||
exempt-issue-labels: "no-stale,help-wanted"
|
||||
stale-issue-message: >
|
||||
|
||||
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.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
|
||||
@@ -40,10 +40,10 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
|
||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||
uses: actions/setup-python@v4.5.0
|
||||
uses: actions/setup-python@v4.4.0
|
||||
with:
|
||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||
|
||||
|
||||
37
.github/workflows/wheels.yml
vendored
37
.github/workflows/wheels.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
||||
architectures: ${{ steps.info.outputs.architectures }}
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
|
||||
- name: Get information
|
||||
id: info
|
||||
@@ -57,13 +57,13 @@ jobs:
|
||||
) > .env_file
|
||||
|
||||
- name: Upload env_file
|
||||
uses: actions/upload-artifact@v3.1.2
|
||||
uses: actions/upload-artifact@v3.1.1
|
||||
with:
|
||||
name: env_file
|
||||
path: ./.env_file
|
||||
|
||||
- name: Upload requirements_diff
|
||||
uses: actions/upload-artifact@v3.1.2
|
||||
uses: actions/upload-artifact@v3.1.1
|
||||
with:
|
||||
name: requirements_diff
|
||||
path: ./requirements_diff.txt
|
||||
@@ -79,7 +79,7 @@ jobs:
|
||||
arch: ${{ fromJson(needs.init.outputs.architectures) }}
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
|
||||
- name: Download env_file
|
||||
uses: actions/download-artifact@v3
|
||||
@@ -116,7 +116,7 @@ jobs:
|
||||
arch: ${{ fromJson(needs.init.outputs.architectures) }}
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v3.3.0
|
||||
uses: actions/checkout@v3.2.0
|
||||
|
||||
- name: Download env_file
|
||||
uses: actions/download-artifact@v3
|
||||
@@ -144,14 +144,6 @@ jobs:
|
||||
sed -i "s|# opencv-python-headless|opencv-python-headless|g" ${requirement_file}
|
||||
done
|
||||
|
||||
- name: Split requirements all
|
||||
run: |
|
||||
# We split requirements all into two different files.
|
||||
# This is to prevent the build from running out of memory when
|
||||
# resolving packages on 32-bits systems (like armhf, armv7).
|
||||
|
||||
split -l $(expr $(expr $(cat requirements_all.txt | wc -l) + 1) / 2) requirements_all.txt requirements_all.txt
|
||||
|
||||
- name: Adjust build env
|
||||
run: |
|
||||
if [ "${{ matrix.arch }}" = "i386" ]; then
|
||||
@@ -167,7 +159,7 @@ jobs:
|
||||
# Do not pin numpy in wheels building
|
||||
sed -i "/numpy/d" homeassistant/package_constraints.txt
|
||||
|
||||
- name: Build wheels (part 1)
|
||||
- name: Build wheels
|
||||
uses: home-assistant/wheels@2022.10.1
|
||||
with:
|
||||
abi: cp310
|
||||
@@ -180,19 +172,4 @@ jobs:
|
||||
legacy: true
|
||||
constraints: "homeassistant/package_constraints.txt"
|
||||
requirements-diff: "requirements_diff.txt"
|
||||
requirements: "requirements_all.txtaa"
|
||||
|
||||
- name: Build wheels (part 2)
|
||||
uses: home-assistant/wheels@2022.10.1
|
||||
with:
|
||||
abi: cp310
|
||||
tag: musllinux_1_2
|
||||
arch: ${{ matrix.arch }}
|
||||
wheels-key: ${{ secrets.WHEELS_KEY }}
|
||||
env-file: true
|
||||
apk: "libexecinfo-dev;bluez-dev;libffi-dev;openssl-dev;glib-dev;eudev-dev;libxml2-dev;libxslt-dev;libpng-dev;libjpeg-turbo-dev;tiff-dev;cups-dev;gmp-dev;mpfr-dev;mpc1-dev;ffmpeg-dev;gammu-dev;yaml-dev;openblas-dev;fftw-dev;lapack-dev;gfortran;blas-dev;eigen-dev;freetype-dev;glew-dev;harfbuzz-dev;hdf5-dev;libdc1394-dev;libtbb-dev;mesa-dev;openexr-dev;openjpeg-dev"
|
||||
skip-binary: aiohttp;grpcio
|
||||
legacy: true
|
||||
constraints: "homeassistant/package_constraints.txt"
|
||||
requirements-diff: "requirements_diff.txt"
|
||||
requirements: "requirements_all.txtab"
|
||||
requirements: "requirements_all.txt"
|
||||
|
||||
@@ -36,11 +36,11 @@ repos:
|
||||
- pycodestyle==2.10.0
|
||||
- pyflakes==3.0.1
|
||||
- flake8-docstrings==1.6.0
|
||||
- pydocstyle==6.2.3
|
||||
- pydocstyle==6.1.1
|
||||
- flake8-comprehensions==3.10.1
|
||||
- flake8-noqa==1.3.0
|
||||
- mccabe==0.7.0
|
||||
exclude: docs/source/conf.py
|
||||
files: ^(homeassistant|script|tests)/.+\.py$
|
||||
- repo: https://github.com/PyCQA/bandit
|
||||
rev: 1.7.4
|
||||
hooks:
|
||||
|
||||
@@ -58,7 +58,6 @@ homeassistant.components.amcrest.*
|
||||
homeassistant.components.ampio.*
|
||||
homeassistant.components.analytics.*
|
||||
homeassistant.components.anthemav.*
|
||||
homeassistant.components.apcupsd.*
|
||||
homeassistant.components.aqualogic.*
|
||||
homeassistant.components.aseko_pool_live.*
|
||||
homeassistant.components.asuswrt.*
|
||||
@@ -69,7 +68,6 @@ homeassistant.components.backup.*
|
||||
homeassistant.components.baf.*
|
||||
homeassistant.components.bayesian.*
|
||||
homeassistant.components.binary_sensor.*
|
||||
homeassistant.components.bitcoin.*
|
||||
homeassistant.components.blockchain.*
|
||||
homeassistant.components.bluetooth.*
|
||||
homeassistant.components.bluetooth_tracker.*
|
||||
@@ -178,7 +176,6 @@ homeassistant.components.lacrosse_view.*
|
||||
homeassistant.components.lametric.*
|
||||
homeassistant.components.laundrify.*
|
||||
homeassistant.components.lcn.*
|
||||
homeassistant.components.ld2410_ble.*
|
||||
homeassistant.components.lidarr.*
|
||||
homeassistant.components.lifx.*
|
||||
homeassistant.components.light.*
|
||||
@@ -249,7 +246,6 @@ homeassistant.components.rituals_perfume_genie.*
|
||||
homeassistant.components.roku.*
|
||||
homeassistant.components.rpi_power.*
|
||||
homeassistant.components.rtsp_to_webrtc.*
|
||||
homeassistant.components.ruuvi_gateway.*
|
||||
homeassistant.components.ruuvitag_ble.*
|
||||
homeassistant.components.samsungtv.*
|
||||
homeassistant.components.scene.*
|
||||
@@ -260,7 +256,6 @@ homeassistant.components.sensibo.*
|
||||
homeassistant.components.sensirion_ble.*
|
||||
homeassistant.components.sensor.*
|
||||
homeassistant.components.senz.*
|
||||
homeassistant.components.sfr_box.*
|
||||
homeassistant.components.shelly.*
|
||||
homeassistant.components.simplepush.*
|
||||
homeassistant.components.simplisafe.*
|
||||
|
||||
43
CODEOWNERS
43
CODEOWNERS
@@ -156,8 +156,6 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/bluesound/ @thrawnarn
|
||||
/homeassistant/components/bluetooth/ @bdraco
|
||||
/tests/components/bluetooth/ @bdraco
|
||||
/homeassistant/components/bluetooth_adapters/ @bdraco
|
||||
/tests/components/bluetooth_adapters/ @bdraco
|
||||
/homeassistant/components/bmw_connected_drive/ @gerard33 @rikroe
|
||||
/tests/components/bmw_connected_drive/ @gerard33 @rikroe
|
||||
/homeassistant/components/bond/ @bdraco @prystupa @joshs85 @marciogranzotto
|
||||
@@ -267,8 +265,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/discord/ @tkdrob
|
||||
/homeassistant/components/discovery/ @home-assistant/core
|
||||
/tests/components/discovery/ @home-assistant/core
|
||||
/homeassistant/components/dlink/ @tkdrob
|
||||
/tests/components/dlink/ @tkdrob
|
||||
/homeassistant/components/dlna_dmr/ @StevenLooman @chishm
|
||||
/tests/components/dlna_dmr/ @StevenLooman @chishm
|
||||
/homeassistant/components/dlna_dms/ @chishm
|
||||
@@ -317,8 +313,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/emulated_kasa/ @kbickar
|
||||
/homeassistant/components/energy/ @home-assistant/core
|
||||
/tests/components/energy/ @home-assistant/core
|
||||
/homeassistant/components/energyzero/ @klaasnicolaas
|
||||
/tests/components/energyzero/ @klaasnicolaas
|
||||
/homeassistant/components/enigma2/ @fbradyirl
|
||||
/homeassistant/components/enocean/ @bdurrer
|
||||
/tests/components/enocean/ @bdurrer
|
||||
@@ -337,8 +331,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/escea/ @lazdavila
|
||||
/homeassistant/components/esphome/ @OttoWinter @jesserockz
|
||||
/tests/components/esphome/ @OttoWinter @jesserockz
|
||||
/homeassistant/components/eufylife_ble/ @bdr99
|
||||
/tests/components/eufylife_ble/ @bdr99
|
||||
/homeassistant/components/evil_genius_labs/ @balloob
|
||||
/tests/components/evil_genius_labs/ @balloob
|
||||
/homeassistant/components/evohome/ @zxdavb
|
||||
@@ -441,8 +433,6 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/google_assistant_sdk/ @tronikos
|
||||
/tests/components/google_assistant_sdk/ @tronikos
|
||||
/homeassistant/components/google_cloud/ @lufton
|
||||
/homeassistant/components/google_mail/ @tkdrob
|
||||
/tests/components/google_mail/ @tkdrob
|
||||
/homeassistant/components/google_sheets/ @tkdrob
|
||||
/tests/components/google_sheets/ @tkdrob
|
||||
/homeassistant/components/google_travel_time/ @eifinger
|
||||
@@ -543,8 +533,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/image_processing/ @home-assistant/core
|
||||
/homeassistant/components/image_upload/ @home-assistant/core
|
||||
/tests/components/image_upload/ @home-assistant/core
|
||||
/homeassistant/components/imap/ @engrbm87
|
||||
/tests/components/imap/ @engrbm87
|
||||
/homeassistant/components/incomfort/ @zxdavb
|
||||
/homeassistant/components/influxdb/ @mdegat01
|
||||
/tests/components/influxdb/ @mdegat01
|
||||
@@ -611,8 +599,6 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/keyboard_remote/ @bendavid @lanrat
|
||||
/homeassistant/components/keymitt_ble/ @spycle
|
||||
/tests/components/keymitt_ble/ @spycle
|
||||
/homeassistant/components/kitchen_sink/ @home-assistant/core
|
||||
/tests/components/kitchen_sink/ @home-assistant/core
|
||||
/homeassistant/components/kmtronic/ @dgomes
|
||||
/tests/components/kmtronic/ @dgomes
|
||||
/homeassistant/components/knx/ @Julius2342 @farmio @marvin-w
|
||||
@@ -639,8 +625,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/laundrify/ @xLarry
|
||||
/homeassistant/components/lcn/ @alengwenus
|
||||
/tests/components/lcn/ @alengwenus
|
||||
/homeassistant/components/ld2410_ble/ @930913
|
||||
/tests/components/ld2410_ble/ @930913
|
||||
/homeassistant/components/led_ble/ @bdraco
|
||||
/tests/components/led_ble/ @bdraco
|
||||
/homeassistant/components/lg_netcast/ @Drafteed
|
||||
@@ -685,6 +669,7 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/lyric/ @timmo001
|
||||
/tests/components/lyric/ @timmo001
|
||||
/homeassistant/components/mastodon/ @fabaff
|
||||
/homeassistant/components/matrix/ @tinloaf
|
||||
/homeassistant/components/matter/ @home-assistant/matter
|
||||
/tests/components/matter/ @home-assistant/matter
|
||||
/homeassistant/components/mazda/ @bdr99
|
||||
@@ -855,11 +840,9 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/openweathermap/ @fabaff @freekode @nzapponi
|
||||
/homeassistant/components/opnsense/ @mtreinish
|
||||
/tests/components/opnsense/ @mtreinish
|
||||
/homeassistant/components/oralb/ @bdraco @conway20
|
||||
/tests/components/oralb/ @bdraco @conway20
|
||||
/homeassistant/components/oralb/ @bdraco
|
||||
/tests/components/oralb/ @bdraco
|
||||
/homeassistant/components/oru/ @bvlaicu
|
||||
/homeassistant/components/otbr/ @home-assistant/core
|
||||
/tests/components/otbr/ @home-assistant/core
|
||||
/homeassistant/components/overkiz/ @imicknl @vlebourl @tetienne @nyroDev
|
||||
/tests/components/overkiz/ @imicknl @vlebourl @tetienne @nyroDev
|
||||
/homeassistant/components/ovo_energy/ @timmo001
|
||||
@@ -997,8 +980,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/rtsp_to_webrtc/ @allenporter
|
||||
/homeassistant/components/ruckus_unleashed/ @gabe565
|
||||
/tests/components/ruckus_unleashed/ @gabe565
|
||||
/homeassistant/components/ruuvi_gateway/ @akx
|
||||
/tests/components/ruuvi_gateway/ @akx
|
||||
/homeassistant/components/ruuvitag_ble/ @akx
|
||||
/tests/components/ruuvitag_ble/ @akx
|
||||
/homeassistant/components/sabnzbd/ @shaiu
|
||||
@@ -1045,8 +1026,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/senz/ @milanmeu
|
||||
/homeassistant/components/serial/ @fabaff
|
||||
/homeassistant/components/seven_segments/ @fabaff
|
||||
/homeassistant/components/sfr_box/ @epenet
|
||||
/tests/components/sfr_box/ @epenet
|
||||
/homeassistant/components/sharkiq/ @JeffResc @funkybunch @AritroSaha10
|
||||
/tests/components/sharkiq/ @JeffResc @funkybunch @AritroSaha10
|
||||
/homeassistant/components/shell_command/ @home-assistant/core
|
||||
@@ -1128,8 +1107,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/srp_energy/ @briglx
|
||||
/homeassistant/components/starline/ @anonym-tsk
|
||||
/tests/components/starline/ @anonym-tsk
|
||||
/homeassistant/components/starlink/ @boswelja
|
||||
/tests/components/starlink/ @boswelja
|
||||
/homeassistant/components/statistics/ @fabaff @ThomDietrich
|
||||
/tests/components/statistics/ @fabaff @ThomDietrich
|
||||
/homeassistant/components/steam_online/ @tkdrob
|
||||
@@ -1316,14 +1293,14 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/weather/ @home-assistant/core
|
||||
/homeassistant/components/webhook/ @home-assistant/core
|
||||
/tests/components/webhook/ @home-assistant/core
|
||||
/homeassistant/components/webostv/ @thecode
|
||||
/tests/components/webostv/ @thecode
|
||||
/homeassistant/components/webostv/ @bendavid @thecode
|
||||
/tests/components/webostv/ @bendavid @thecode
|
||||
/homeassistant/components/websocket_api/ @home-assistant/core
|
||||
/tests/components/websocket_api/ @home-assistant/core
|
||||
/homeassistant/components/wemo/ @esev
|
||||
/tests/components/wemo/ @esev
|
||||
/homeassistant/components/whirlpool/ @abmantis @mkmer
|
||||
/tests/components/whirlpool/ @abmantis @mkmer
|
||||
/homeassistant/components/whirlpool/ @abmantis
|
||||
/tests/components/whirlpool/ @abmantis
|
||||
/homeassistant/components/whois/ @frenck
|
||||
/tests/components/whois/ @frenck
|
||||
/homeassistant/components/wiffi/ @mampfes
|
||||
@@ -1379,8 +1356,6 @@ build.json @home-assistant/supervisor
|
||||
/tests/components/zeroconf/ @bdraco
|
||||
/homeassistant/components/zerproc/ @emlove
|
||||
/tests/components/zerproc/ @emlove
|
||||
/homeassistant/components/zeversolar/ @kvanzuijlen
|
||||
/tests/components/zeversolar/ @kvanzuijlen
|
||||
/homeassistant/components/zha/ @dmulcahey @adminiuga @puddly
|
||||
/tests/components/zha/ @dmulcahey @adminiuga @puddly
|
||||
/homeassistant/components/zodiac/ @JulienTant
|
||||
@@ -1390,8 +1365,8 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/zoneminder/ @rohankapoorcom
|
||||
/homeassistant/components/zwave_js/ @home-assistant/z-wave
|
||||
/tests/components/zwave_js/ @home-assistant/z-wave
|
||||
/homeassistant/components/zwave_me/ @lawfulchaos @Z-Wave-Me @PoltoS
|
||||
/tests/components/zwave_me/ @lawfulchaos @Z-Wave-Me @PoltoS
|
||||
/homeassistant/components/zwave_me/ @lawfulchaos @Z-Wave-Me
|
||||
/tests/components/zwave_me/ @lawfulchaos @Z-Wave-Me
|
||||
|
||||
# Individual files
|
||||
/homeassistant/components/demo/weather.py @fabaff
|
||||
|
||||
47
Dockerfile
47
Dockerfile
@@ -11,51 +11,22 @@ WORKDIR /usr/src
|
||||
COPY requirements.txt homeassistant/
|
||||
COPY homeassistant/package_constraints.txt homeassistant/homeassistant/
|
||||
RUN \
|
||||
pip3 install \
|
||||
--no-cache-dir \
|
||||
--no-index \
|
||||
--only-binary=:all: \
|
||||
--find-links "${WHEELS_LINKS}" \
|
||||
--use-deprecated=legacy-resolver \
|
||||
-r homeassistant/requirements.txt
|
||||
|
||||
COPY requirements_all.txt home_assistant_frontend-* home_assistant_intents-* homeassistant/
|
||||
pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \
|
||||
-r homeassistant/requirements.txt --use-deprecated=legacy-resolver
|
||||
COPY requirements_all.txt home_assistant_frontend-* homeassistant/
|
||||
RUN \
|
||||
if ls homeassistant/home_assistant_frontend*.whl 1> /dev/null 2>&1; then \
|
||||
pip3 install \
|
||||
--no-cache-dir \
|
||||
--no-index \
|
||||
homeassistant/home_assistant_frontend-*.whl; \
|
||||
pip3 install --no-cache-dir --no-index homeassistant/home_assistant_frontend-*.whl; \
|
||||
fi \
|
||||
&& if ls homeassistant/home_assistant_intents*.whl 1> /dev/null 2>&1; then \
|
||||
pip3 install \
|
||||
--no-cache-dir \
|
||||
--no-index \
|
||||
homeassistant/home_assistant_intents-*.whl; \
|
||||
fi \
|
||||
&& \
|
||||
LD_PRELOAD="/usr/local/lib/libjemalloc.so.2" \
|
||||
MALLOC_CONF="background_thread:true,metadata_thp:auto,dirty_decay_ms:20000,muzzy_decay_ms:20000" \
|
||||
pip3 install \
|
||||
--no-cache-dir \
|
||||
--no-index \
|
||||
--only-binary=:all: \
|
||||
--find-links "${WHEELS_LINKS}" \
|
||||
--use-deprecated=legacy-resolver \
|
||||
-r homeassistant/requirements_all.txt
|
||||
&& pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \
|
||||
-r homeassistant/requirements_all.txt --use-deprecated=legacy-resolver
|
||||
|
||||
## Setup Home Assistant Core
|
||||
COPY . homeassistant/
|
||||
RUN \
|
||||
pip3 install \
|
||||
--no-cache-dir \
|
||||
--no-index \
|
||||
--only-binary=:all: \
|
||||
--find-links "${WHEELS_LINKS}" \
|
||||
--use-deprecated=legacy-resolver \
|
||||
-e ./homeassistant \
|
||||
&& python3 -m compileall \
|
||||
homeassistant/homeassistant
|
||||
pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \
|
||||
-e ./homeassistant --use-deprecated=legacy-resolver \
|
||||
&& python3 -m compileall homeassistant/homeassistant
|
||||
|
||||
# Home Assistant S6-Overlay
|
||||
COPY rootfs /
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"""
|
||||
Sphinx extension for ReadTheDocs-style "Edit on GitHub" links on the sidebar.
|
||||
Sphinx extension to add ReadTheDocs-style "Edit on GitHub" links to the
|
||||
sidebar.
|
||||
|
||||
Loosely based on https://github.com/astropy/astropy/pull/347
|
||||
"""
|
||||
@@ -11,7 +12,6 @@ __licence__ = "BSD (3 clause)"
|
||||
|
||||
|
||||
def get_github_url(app, view, path):
|
||||
"""Build the GitHub URL."""
|
||||
return (
|
||||
f"https://github.com/{app.config.edit_on_github_project}/"
|
||||
f"{view}/{app.config.edit_on_github_branch}/"
|
||||
@@ -20,7 +20,6 @@ def get_github_url(app, view, path):
|
||||
|
||||
|
||||
def html_page_context(app, pagename, templatename, context, doctree):
|
||||
"""Build the HTML page."""
|
||||
if templatename != "page.html":
|
||||
return
|
||||
|
||||
@@ -39,7 +38,6 @@ def html_page_context(app, pagename, templatename, context, doctree):
|
||||
|
||||
|
||||
def setup(app):
|
||||
"""Set up the app."""
|
||||
app.add_config_value("edit_on_github_project", "", True)
|
||||
app.add_config_value("edit_on_github_branch", "master", True)
|
||||
app.add_config_value("edit_on_github_src_path", "", True) # 'eg' "docs/"
|
||||
|
||||
@@ -25,7 +25,7 @@ from homeassistant.const import __short_version__, __version__
|
||||
PROJECT_NAME = "Home Assistant"
|
||||
PROJECT_PACKAGE_NAME = "homeassistant"
|
||||
PROJECT_AUTHOR = "The Home Assistant Authors"
|
||||
PROJECT_COPYRIGHT = PROJECT_AUTHOR
|
||||
PROJECT_COPYRIGHT = f" 2013-2020, {PROJECT_AUTHOR}"
|
||||
PROJECT_LONG_DESCRIPTION = (
|
||||
"Home Assistant is an open-source "
|
||||
"home automation platform running on Python 3. "
|
||||
|
||||
@@ -15,10 +15,7 @@ FAULT_LOG_FILENAME = "home-assistant.log.fault"
|
||||
def validate_os() -> None:
|
||||
"""Validate that Home Assistant is running in a supported operating system."""
|
||||
if not sys.platform.startswith(("darwin", "linux")):
|
||||
print(
|
||||
"Home Assistant only supports Linux, OSX and Windows using WSL",
|
||||
file=sys.stderr,
|
||||
)
|
||||
print("Home Assistant only supports Linux, OSX and Windows using WSL")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@@ -27,8 +24,7 @@ def validate_python() -> None:
|
||||
if sys.version_info[:3] < REQUIRED_PYTHON_VER:
|
||||
print(
|
||||
"Home Assistant requires at least Python "
|
||||
f"{REQUIRED_PYTHON_VER[0]}.{REQUIRED_PYTHON_VER[1]}.{REQUIRED_PYTHON_VER[2]}",
|
||||
file=sys.stderr,
|
||||
f"{REQUIRED_PYTHON_VER[0]}.{REQUIRED_PYTHON_VER[1]}.{REQUIRED_PYTHON_VER[2]}"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
@@ -43,23 +39,18 @@ def ensure_config_path(config_dir: str) -> None:
|
||||
# Test if configuration directory exists
|
||||
if not os.path.isdir(config_dir):
|
||||
if config_dir != config_util.get_default_config_dir():
|
||||
if os.path.exists(config_dir):
|
||||
reason = "is not a directory"
|
||||
else:
|
||||
reason = "does not exist"
|
||||
print(
|
||||
f"Fatal Error: Specified configuration directory {config_dir} {reason}",
|
||||
file=sys.stderr,
|
||||
f"Fatal Error: Specified configuration directory {config_dir} "
|
||||
"does not exist"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
os.mkdir(config_dir)
|
||||
except OSError as ex:
|
||||
except OSError:
|
||||
print(
|
||||
"Fatal Error: Unable to create default configuration "
|
||||
f"directory {config_dir}: {ex}",
|
||||
file=sys.stderr,
|
||||
f"directory {config_dir}"
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
@@ -67,11 +58,8 @@ def ensure_config_path(config_dir: str) -> None:
|
||||
if not os.path.isdir(lib_dir):
|
||||
try:
|
||||
os.mkdir(lib_dir)
|
||||
except OSError as ex:
|
||||
print(
|
||||
f"Fatal Error: Unable to create library directory {lib_dir}: {ex}",
|
||||
file=sys.stderr,
|
||||
)
|
||||
except OSError:
|
||||
print(f"Fatal Error: Unable to create library directory {lib_dir}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
@@ -555,9 +555,7 @@ class AuthStore:
|
||||
"client_icon": refresh_token.client_icon,
|
||||
"token_type": refresh_token.token_type,
|
||||
"created_at": refresh_token.created_at.isoformat(),
|
||||
"access_token_expiration": (
|
||||
refresh_token.access_token_expiration.total_seconds()
|
||||
),
|
||||
"access_token_expiration": refresh_token.access_token_expiration.total_seconds(),
|
||||
"token": refresh_token.token,
|
||||
"jwt_key": refresh_token.jwt_key,
|
||||
"last_used_at": refresh_token.last_used_at.isoformat()
|
||||
|
||||
@@ -8,9 +8,7 @@ from .util.async_ import protect_loop
|
||||
def enable() -> None:
|
||||
"""Enable the detection of blocking calls in the event loop."""
|
||||
# Prevent urllib3 and requests doing I/O in event loop
|
||||
HTTPConnection.putrequest = protect_loop( # type: ignore[assignment]
|
||||
HTTPConnection.putrequest
|
||||
)
|
||||
HTTPConnection.putrequest = protect_loop(HTTPConnection.putrequest) # type: ignore[assignment]
|
||||
|
||||
# Prevent sleeping in event loop. Non-strict since 2022.02
|
||||
time.sleep = protect_loop(time.sleep, strict=False)
|
||||
|
||||
@@ -385,11 +385,7 @@ def async_enable_logging(
|
||||
)
|
||||
threading.excepthook = lambda args: logging.getLogger(None).exception(
|
||||
"Uncaught thread exception",
|
||||
exc_info=( # type: ignore[arg-type]
|
||||
args.exc_type,
|
||||
args.exc_value,
|
||||
args.exc_traceback,
|
||||
),
|
||||
exc_info=(args.exc_type, args.exc_value, args.exc_traceback), # type: ignore[arg-type]
|
||||
)
|
||||
|
||||
# Log errors to a file if we have write access to file or config dir
|
||||
@@ -407,10 +403,7 @@ def async_enable_logging(
|
||||
not err_path_exists and os.access(err_dir, os.W_OK)
|
||||
):
|
||||
|
||||
err_handler: (
|
||||
logging.handlers.RotatingFileHandler
|
||||
| logging.handlers.TimedRotatingFileHandler
|
||||
)
|
||||
err_handler: logging.handlers.RotatingFileHandler | logging.handlers.TimedRotatingFileHandler
|
||||
if log_rotate_days:
|
||||
err_handler = logging.handlers.TimedRotatingFileHandler(
|
||||
err_log_path, when="midnight", backupCount=log_rotate_days
|
||||
@@ -469,10 +462,7 @@ def _get_domains(hass: core.HomeAssistant, config: dict[str, Any]) -> set[str]:
|
||||
|
||||
|
||||
async def _async_watch_pending_setups(hass: core.HomeAssistant) -> None:
|
||||
"""Periodic log of setups that are pending.
|
||||
|
||||
Pending for longer than LOG_SLOW_STARTUP_INTERVAL.
|
||||
"""
|
||||
"""Periodic log of setups that are pending for longer than LOG_SLOW_STARTUP_INTERVAL."""
|
||||
loop_count = 0
|
||||
setup_started: dict[str, datetime] = hass.data[DATA_SETUP_STARTED]
|
||||
previous_was_empty = True
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"domain": "amazon",
|
||||
"name": "Amazon",
|
||||
"integrations": ["alexa", "amazon_polly", "aws", "fire_tv", "route53"]
|
||||
"integrations": ["alexa", "amazon_polly", "aws", "route53"]
|
||||
}
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"domain": "eufy",
|
||||
"name": "eufy",
|
||||
"integrations": ["eufy", "eufylife_ble"],
|
||||
"iot_standards": []
|
||||
}
|
||||
@@ -6,7 +6,6 @@
|
||||
"google_assistant_sdk",
|
||||
"google_cloud",
|
||||
"google_domains",
|
||||
"google_mail",
|
||||
"google_maps",
|
||||
"google_pubsub",
|
||||
"google_sheets",
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Slapta\u017eodis",
|
||||
"username": "El. pa\u0161tas"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
"""Diagnostics support for AccuWeather."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
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
|
||||
@@ -16,7 +14,7 @@ TO_REDACT = {CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE}
|
||||
|
||||
async def async_get_config_entry_diagnostics(
|
||||
hass: HomeAssistant, config_entry: ConfigEntry
|
||||
) -> dict[str, Any]:
|
||||
) -> dict:
|
||||
"""Return diagnostics for a config entry."""
|
||||
coordinator: AccuWeatherDataUpdateCoordinator = hass.data[DOMAIN][
|
||||
config_entry.entry_id
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"domain": "accuweather",
|
||||
"name": "AccuWeather",
|
||||
"documentation": "https://www.home-assistant.io/integrations/accuweather/",
|
||||
"requirements": ["accuweather==0.5.0"],
|
||||
"requirements": ["accuweather==0.4.0"],
|
||||
"codeowners": ["@bieniu"],
|
||||
"config_flow": true,
|
||||
"quality_scale": "platinum",
|
||||
|
||||
@@ -22,27 +22,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"pressure_tendency": {
|
||||
"state": {
|
||||
"falling": "D\u00fc\u015f\u00fcyor",
|
||||
"rising": "Y\u00fckseliyor",
|
||||
"steady": "Sabit"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
"data": {
|
||||
"forecast": "Hava Durumu tahmini"
|
||||
},
|
||||
"description": "AccuWeather API anahtar\u0131n\u0131n \u00fccretsiz s\u00fcr\u00fcm\u00fcn\u00fcn s\u0131n\u0131rlamalar\u0131 nedeniyle, hava tahminini etkinle\u015ftirdi\u011finizde, veri g\u00fcncellemeleri her 40 dakikada bir yerine 80 dakikada bir ger\u00e7ekle\u015ftirilir."
|
||||
}
|
||||
}
|
||||
},
|
||||
"system_health": {
|
||||
"info": {
|
||||
"can_reach_server": "AccuWeather sunucusuna ula\u015f\u0131n",
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"invalid_auth": "\u041d\u0435\u0434\u0456\u0439\u0441\u043d\u0430 \u0430\u0432\u0442\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u044f"
|
||||
},
|
||||
"step": {
|
||||
"cloud": {
|
||||
"data": {
|
||||
"account_id": "ID \u041e\u0431\u043b\u0456\u043a\u043e\u0432\u043e\u0433\u043e \u0437\u0430\u043f\u0438\u0441\u0443",
|
||||
"password": "\u041f\u0430\u0440\u043e\u043b\u044c"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,12 +58,7 @@ class AdGuardHomeEntity(Entity):
|
||||
return DeviceInfo(
|
||||
entry_type=DeviceEntryType.SERVICE,
|
||||
identifiers={
|
||||
( # type: ignore[arg-type]
|
||||
DOMAIN,
|
||||
self.adguard.host,
|
||||
self.adguard.port,
|
||||
self.adguard.base_path,
|
||||
)
|
||||
(DOMAIN, self.adguard.host, self.adguard.port, self.adguard.base_path) # type: ignore[arg-type]
|
||||
},
|
||||
manufacturer="AdGuard Team",
|
||||
name="AdGuard Home",
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "Slapta\u017eodis"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
"longitude": "\u0393\u03b5\u03c9\u03b3\u03c1\u03b1\u03c6\u03b9\u03ba\u03cc \u03bc\u03ae\u03ba\u03bf\u03c2",
|
||||
"name": "\u038c\u03bd\u03bf\u03bc\u03b1 \u03c4\u03b7\u03c2 \u03b5\u03bd\u03c3\u03c9\u03bc\u03ac\u03c4\u03c9\u03c3\u03b7\u03c2"
|
||||
},
|
||||
"description": "\u0393\u03b9\u03b1 \u03bd\u03b1 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03c3\u03b5\u03c4\u03b5 \u03ba\u03bb\u03b5\u03b9\u03b4\u03af API, \u03bc\u03b5\u03c4\u03b1\u03b2\u03b5\u03af\u03c4\u03b5 \u03c3\u03c4\u03b7 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 https://opendata.aemet.es/centrodedescargas/altaUsuario"
|
||||
"description": "\u03a1\u03cd\u03b8\u03bc\u03b9\u03c3\u03b7 \u03c4\u03b7\u03c2 \u03b5\u03bd\u03c3\u03c9\u03bc\u03ac\u03c4\u03c9\u03c3\u03b7\u03c2 \u03c4\u03bf\u03c5 AEMET OpenData. \u0393\u03b9\u03b1 \u03bd\u03b1 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03c3\u03b5\u03c4\u03b5 \u03c4\u03bf \u03ba\u03bb\u03b5\u03b9\u03b4\u03af API \u03bc\u03b5\u03c4\u03b1\u03b2\u03b5\u03af\u03c4\u03b5 \u03c3\u03c4\u03b7 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 https://opendata.aemet.es/centrodedescargas/altaUsuario"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -150,9 +150,7 @@ class AirlyDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
"""Initialize."""
|
||||
self.latitude = latitude
|
||||
self.longitude = longitude
|
||||
# Currently, Airly only supports Polish and English
|
||||
language = "pl" if hass.config.language == "pl" else "en"
|
||||
self.airly = Airly(api_key, session, language=language)
|
||||
self.airly = Airly(api_key, session)
|
||||
self.use_nearest = use_nearest
|
||||
|
||||
super().__init__(hass, _LOGGER, name=DOMAIN, update_interval=update_interval)
|
||||
|
||||
@@ -46,7 +46,7 @@ class AirlyFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
user_input["longitude"],
|
||||
)
|
||||
if not location_point_valid:
|
||||
location_nearest_valid = await test_location(
|
||||
await test_location(
|
||||
websession,
|
||||
user_input["api_key"],
|
||||
user_input["latitude"],
|
||||
@@ -60,8 +60,6 @@ class AirlyFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
errors["base"] = "wrong_location"
|
||||
else:
|
||||
if not location_point_valid:
|
||||
if not location_nearest_valid:
|
||||
return self.async_abort(reason="wrong_location")
|
||||
use_nearest = True
|
||||
return self.async_create_entry(
|
||||
title=user_input[CONF_NAME],
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"""Diagnostics support for Airly."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.diagnostics import async_redact_data
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
@@ -21,7 +19,7 @@ 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[str, Any]:
|
||||
) -> dict:
|
||||
"""Return diagnostics for a config entry."""
|
||||
coordinator: AirlyDataUpdateCoordinator = hass.data[DOMAIN][config_entry.entry_id]
|
||||
|
||||
|
||||
@@ -16,8 +16,7 @@
|
||||
"invalid_api_key": "[%key:common::config_flow::error::invalid_api_key%]"
|
||||
},
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_location%]",
|
||||
"wrong_location": "No Airly measuring stations in this area."
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_location%]"
|
||||
}
|
||||
},
|
||||
"system_health": {
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "La ubicaci\u00f3 ja est\u00e0 configurada",
|
||||
"wrong_location": "No hi ha estacions de mesura Airly en aquesta zona."
|
||||
"already_configured": "La ubicaci\u00f3 ja est\u00e0 configurada"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Clau API inv\u00e0lida",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Standort ist bereits konfiguriert",
|
||||
"wrong_location": "Keine Airly Luftmessstation an diesem Ort"
|
||||
"already_configured": "Standort ist bereits konfiguriert"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Ung\u00fcltiger API-Schl\u00fcssel",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u0397 \u03c4\u03bf\u03c0\u03bf\u03b8\u03b5\u03c3\u03af\u03b1 \u03ad\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03b4\u03b9\u03b1\u03bc\u03bf\u03c1\u03c6\u03c9\u03b8\u03b5\u03af",
|
||||
"wrong_location": "\u0394\u03b5\u03bd \u03c5\u03c0\u03ac\u03c1\u03c7\u03bf\u03c5\u03bd \u03c3\u03c4\u03b1\u03b8\u03bc\u03bf\u03af \u03bc\u03ad\u03c4\u03c1\u03b7\u03c3\u03b7\u03c2 Airly \u03c3\u03b5 \u03b1\u03c5\u03c4\u03ae\u03bd \u03c4\u03b7\u03bd \u03c0\u03b5\u03c1\u03b9\u03bf\u03c7\u03ae."
|
||||
"already_configured": "\u0397 \u03c4\u03bf\u03c0\u03bf\u03b8\u03b5\u03c3\u03af\u03b1 \u03ad\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03b4\u03b9\u03b1\u03bc\u03bf\u03c1\u03c6\u03c9\u03b8\u03b5\u03af"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "\u0386\u03ba\u03c5\u03c1\u03bf API \u03ba\u03bb\u03b5\u03b9\u03b4\u03af",
|
||||
@@ -16,7 +15,7 @@
|
||||
"longitude": "\u0393\u03b5\u03c9\u03b3\u03c1\u03b1\u03c6\u03b9\u03ba\u03cc \u03bc\u03ae\u03ba\u03bf\u03c2",
|
||||
"name": "\u038c\u03bd\u03bf\u03bc\u03b1"
|
||||
},
|
||||
"description": "\u0393\u03b9\u03b1 \u03bd\u03b1 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03c3\u03b5\u03c4\u03b5 \u03ba\u03bb\u03b5\u03b9\u03b4\u03af API, \u03bc\u03b5\u03c4\u03b1\u03b2\u03b5\u03af\u03c4\u03b5 \u03c3\u03c4\u03b7 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 https://developer.airly.eu/register"
|
||||
"description": "\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03c4\u03b5 \u03c4\u03b7\u03bd \u03b5\u03bd\u03c3\u03c9\u03bc\u03ac\u03c4\u03c9\u03c3\u03b7 \u03c0\u03bf\u03b9\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2 \u03b1\u03ad\u03c1\u03b1 Airly. \u0393\u03b9\u03b1 \u03bd\u03b1 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03c3\u03b5\u03c4\u03b5 \u03ba\u03bb\u03b5\u03b9\u03b4\u03af API, \u03bc\u03b5\u03c4\u03b1\u03b2\u03b5\u03af\u03c4\u03b5 \u03c3\u03c4\u03b7 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 https://developer.airly.eu/register"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Location is already configured",
|
||||
"wrong_location": "No Airly measuring stations in this area."
|
||||
"already_configured": "Location is already configured"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Invalid API key",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "La ubicaci\u00f3n ya est\u00e1 configurada",
|
||||
"wrong_location": "No hay estaciones de medici\u00f3n Airly en esta \u00e1rea."
|
||||
"already_configured": "La ubicaci\u00f3n ya est\u00e1 configurada"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Clave API no v\u00e1lida",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Asukoht on juba m\u00e4\u00e4ratud",
|
||||
"wrong_location": "Selles piirkonnas pole Airly m\u00f5\u00f5tejaamu."
|
||||
"already_configured": "Asukoht on juba m\u00e4\u00e4ratud"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Vigane API v\u00f5ti",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "A hely m\u00e1r konfigur\u00e1lva van",
|
||||
"wrong_location": "Ezen a ter\u00fcleten nincs Airly m\u00e9r\u0151\u00e1llom\u00e1s."
|
||||
"already_configured": "A hely m\u00e1r konfigur\u00e1lva van"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "\u00c9rv\u00e9nytelen API kulcs",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Lokasi sudah dikonfigurasi",
|
||||
"wrong_location": "Tidak ada stasiun pengukur Airly di daerah ini."
|
||||
"already_configured": "Lokasi sudah dikonfigurasi"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Kunci API tidak valid",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "La posizione \u00e8 gi\u00e0 configurata",
|
||||
"wrong_location": "Nessuna stazione di misurazione Airly in quest'area."
|
||||
"already_configured": "La posizione \u00e8 gi\u00e0 configurata"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Chiave API non valida",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Locatie is al geconfigureerd",
|
||||
"wrong_location": "Geen Airly meetstations in deze ruimte."
|
||||
"already_configured": "Locatie is al geconfigureerd"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Ongeldige API-sleutel",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Plasseringen er allerede konfigurert",
|
||||
"wrong_location": "Ingen Airly m\u00e5lestasjoner i dette omr\u00e5det."
|
||||
"already_configured": "Plasseringen er allerede konfigurert"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Ugyldig API-n\u00f8kkel",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Lokalizacja jest ju\u017c skonfigurowana",
|
||||
"wrong_location": "Brak stacji pomiarowych Airly w tym rejonie"
|
||||
"already_configured": "Lokalizacja jest ju\u017c skonfigurowana"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Nieprawid\u0142owy klucz API",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Localiza\u00e7\u00e3o j\u00e1 est\u00e1 configurada",
|
||||
"wrong_location": "Nenhuma esta\u00e7\u00e3o de medi\u00e7\u00e3o Airly nesta \u00e1rea."
|
||||
"already_configured": "Localiza\u00e7\u00e3o j\u00e1 est\u00e1 configurada"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Chave de API inv\u00e1lida",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430.",
|
||||
"wrong_location": "\u0412 \u044d\u0442\u043e\u0439 \u043e\u0431\u043b\u0430\u0441\u0442\u0438 \u043d\u0435\u0442 \u0438\u0437\u043c\u0435\u0440\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u0441\u0442\u0430\u043d\u0446\u0438\u0439 Airly."
|
||||
"already_configured": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0443\u0436\u0435 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0430."
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "\u041d\u0435\u0432\u0435\u0440\u043d\u044b\u0439 \u043a\u043b\u044e\u0447 API.",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Umiestnenie u\u017e je nakonfigurovan\u00e9",
|
||||
"wrong_location": "V tejto oblasti nie s\u00fa \u017eiadne meracie stanice Airly."
|
||||
"already_configured": "Umiestnenie u\u017e je nakonfigurovan\u00e9"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Neplatn\u00fd API k\u013e\u00fa\u010d",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Konum zaten yap\u0131land\u0131r\u0131lm\u0131\u015f",
|
||||
"wrong_location": "Bu b\u00f6lgede Airly \u00f6l\u00e7\u00fcm istasyonu yok."
|
||||
"already_configured": "Konum zaten yap\u0131land\u0131r\u0131lm\u0131\u015f"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "Ge\u00e7ersiz API anahtar\u0131",
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u5ea7\u6a19\u5df2\u7d93\u8a2d\u5b9a\u5b8c\u6210",
|
||||
"wrong_location": "\u8a72\u5340\u57df\u6c92\u6709 Arily \u76e3\u6e2c\u7ad9\u3002"
|
||||
"already_configured": "\u5ea7\u6a19\u5df2\u7d93\u8a2d\u5b9a\u5b8c\u6210"
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "API \u91d1\u9470\u7121\u6548",
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"longitude": "\u0393\u03b5\u03c9\u03b3\u03c1\u03b1\u03c6\u03b9\u03ba\u03cc \u03bc\u03ae\u03ba\u03bf\u03c2",
|
||||
"radius": "\u0391\u03ba\u03c4\u03af\u03bd\u03b1 \u03c3\u03c4\u03b1\u03b8\u03bc\u03bf\u03cd (\u03bc\u03af\u03bb\u03b9\u03b1, \u03c0\u03c1\u03bf\u03b1\u03b9\u03c1\u03b5\u03c4\u03b9\u03ba\u03cc)"
|
||||
},
|
||||
"description": "\u0393\u03b9\u03b1 \u03bd\u03b1 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03c3\u03b5\u03c4\u03b5 \u03ba\u03bb\u03b5\u03b9\u03b4\u03af API, \u03bc\u03b5\u03c4\u03b1\u03b2\u03b5\u03af\u03c4\u03b5 \u03c3\u03c4\u03b7 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 https://docs.airnowapi.org/account/request/"
|
||||
"description": "\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03c4\u03b5 \u03c4\u03b7\u03bd \u03b5\u03bd\u03c3\u03c9\u03bc\u03ac\u03c4\u03c9\u03c3\u03b7 \u03c4\u03bf\u03c5 AirNow \u03b3\u03b9\u03b1 \u03c4\u03b7\u03bd \u03c0\u03bf\u03b9\u03cc\u03c4\u03b7\u03c4\u03b1 \u03c4\u03bf\u03c5 \u03b1\u03ad\u03c1\u03b1. \u0393\u03b9\u03b1 \u03bd\u03b1 \u03b4\u03b7\u03bc\u03b9\u03bf\u03c5\u03c1\u03b3\u03ae\u03c3\u03b5\u03c4\u03b5 \u03c4\u03bf \u03ba\u03bb\u03b5\u03b9\u03b4\u03af API \u03bc\u03b5\u03c4\u03b1\u03b2\u03b5\u03af\u03c4\u03b5 \u03c3\u03c4\u03b7 \u03b4\u03b9\u03b5\u03cd\u03b8\u03c5\u03bd\u03c3\u03b7 https://docs.airnowapi.org/account/request/"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Cihaz zaten yap\u0131land\u0131r\u0131lm\u0131\u015f"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Ba\u011flanma hatas\u0131",
|
||||
"invalid_auth": "Ge\u00e7ersiz kimlik do\u011frulama",
|
||||
"invalid_input": "Ge\u00e7ersiz ana bilgisayar ad\u0131 veya IP adresi"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"ip_address": "IP Adresi",
|
||||
"password": "Parola"
|
||||
},
|
||||
"description": "Cihaz\u0131n IP adresini veya mDNS'sini ve \u015fifresini sa\u011flay\u0131n",
|
||||
"title": "Cihaz\u0131 tan\u0131mlay\u0131n"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "\u041f\u0430\u0440\u043e\u043b\u044c"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/airthings_ble",
|
||||
"requirements": ["airthings-ble==0.5.3"],
|
||||
"dependencies": ["bluetooth_adapters"],
|
||||
"dependencies": ["bluetooth"],
|
||||
"codeowners": ["@vincegio"],
|
||||
"iot_class": "local_polling",
|
||||
"bluetooth": [
|
||||
|
||||
@@ -154,7 +154,7 @@ class AirthingsSensor(
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: DataUpdateCoordinator[AirthingsDevice],
|
||||
coordinator: DataUpdateCoordinator,
|
||||
airthings_device: AirthingsDevice,
|
||||
entity_description: SensorEntityDescription,
|
||||
) -> None:
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"unknown": "Neo\u010dek\u00e1van\u00e1 chyba"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,13 +10,13 @@
|
||||
"flow_title": "{name}",
|
||||
"step": {
|
||||
"bluetooth_confirm": {
|
||||
"description": "{name} 'i kurmak istiyor musunuz?"
|
||||
"description": "{name} kurulumunu yapmak istiyor musunuz?"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"address": "Cihaz"
|
||||
},
|
||||
"description": "Kurmak i\u00e7in bir cihaz se\u00e7in"
|
||||
"description": "Kurulum i\u00e7in bir cihaz se\u00e7in"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
"data": {
|
||||
"host": "\u039a\u03b5\u03bd\u03c4\u03c1\u03b9\u03ba\u03cc\u03c2 \u03c5\u03c0\u03bf\u03bb\u03bf\u03b3\u03b9\u03c3\u03c4\u03ae\u03c2"
|
||||
},
|
||||
"title": "\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03c4\u03b5 \u03c4\u03b1 \u03c3\u03c4\u03bf\u03b9\u03c7\u03b5\u03af\u03b1 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7\u03c2 AirTouch 4."
|
||||
"title": "\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03c4\u03b5 \u03c4\u03b1 \u03c3\u03c4\u03bf\u03b9\u03c7\u03b5\u03af\u03b1 \u03c3\u03cd\u03bd\u03b4\u03b5\u03c3\u03b7\u03c2 \u03c4\u03bf\u03c5 {intergration}."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ DOMAIN_AIRVISUAL_PRO = "airvisual_pro"
|
||||
PLATFORMS = [Platform.SENSOR]
|
||||
|
||||
DEFAULT_ATTRIBUTION = "Data provided by AirVisual"
|
||||
DEFAULT_NODE_PRO_UPDATE_INTERVAL = timedelta(minutes=1)
|
||||
|
||||
CONFIG_SCHEMA = cv.removed(DOMAIN, raise_if_present=False)
|
||||
|
||||
|
||||
@@ -132,14 +132,15 @@ class AirVisualFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
LOGGER.error(err)
|
||||
errors["base"] = "unknown"
|
||||
|
||||
if errors:
|
||||
return self.async_show_form(
|
||||
step_id=error_step, data_schema=error_schema, errors=errors
|
||||
)
|
||||
|
||||
valid_keys.add(user_input[CONF_API_KEY])
|
||||
|
||||
if existing_entry := await self.async_set_unique_id(self._geo_id):
|
||||
if errors:
|
||||
return self.async_show_form(
|
||||
step_id=error_step, data_schema=error_schema, errors=errors
|
||||
)
|
||||
|
||||
existing_entry = await self.async_set_unique_id(self._geo_id)
|
||||
if existing_entry:
|
||||
self.hass.config_entries.async_update_entry(existing_entry, data=user_input)
|
||||
self.hass.async_create_task(
|
||||
self.hass.config_entries.async_reload(existing_entry.entry_id)
|
||||
|
||||
@@ -19,8 +19,11 @@ from homeassistant.const import (
|
||||
CONF_LONGITUDE,
|
||||
CONF_SHOW_ON_MAP,
|
||||
CONF_STATE,
|
||||
PERCENTAGE,
|
||||
UnitOfTemperature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
|
||||
|
||||
@@ -34,8 +37,17 @@ ATTR_POLLUTANT_UNIT = "pollutant_unit"
|
||||
ATTR_REGION = "region"
|
||||
|
||||
SENSOR_KIND_AQI = "air_quality_index"
|
||||
SENSOR_KIND_BATTERY_LEVEL = "battery_level"
|
||||
SENSOR_KIND_CO2 = "carbon_dioxide"
|
||||
SENSOR_KIND_HUMIDITY = "humidity"
|
||||
SENSOR_KIND_LEVEL = "air_pollution_level"
|
||||
SENSOR_KIND_PM_0_1 = "particulate_matter_0_1"
|
||||
SENSOR_KIND_PM_1_0 = "particulate_matter_1_0"
|
||||
SENSOR_KIND_PM_2_5 = "particulate_matter_2_5"
|
||||
SENSOR_KIND_POLLUTANT = "main_pollutant"
|
||||
SENSOR_KIND_SENSOR_LIFE = "sensor_life"
|
||||
SENSOR_KIND_TEMPERATURE = "temperature"
|
||||
SENSOR_KIND_VOC = "voc"
|
||||
|
||||
GEOGRAPHY_SENSOR_DESCRIPTIONS = (
|
||||
SensorEntityDescription(
|
||||
@@ -70,6 +82,70 @@ GEOGRAPHY_SENSOR_DESCRIPTIONS = (
|
||||
)
|
||||
GEOGRAPHY_SENSOR_LOCALES = {"cn": "Chinese", "us": "U.S."}
|
||||
|
||||
NODE_PRO_SENSOR_DESCRIPTIONS = (
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_AQI,
|
||||
name="Air quality index",
|
||||
device_class=SensorDeviceClass.AQI,
|
||||
native_unit_of_measurement="AQI",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_BATTERY_LEVEL,
|
||||
name="Battery",
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_CO2,
|
||||
name="C02",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_HUMIDITY,
|
||||
name="Humidity",
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_PM_0_1,
|
||||
name="PM 0.1",
|
||||
device_class=SensorDeviceClass.PM1,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_PM_1_0,
|
||||
name="PM 1.0",
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_PM_2_5,
|
||||
name="PM 2.5",
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_TEMPERATURE,
|
||||
name="Temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_VOC,
|
||||
name="VOC",
|
||||
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
)
|
||||
|
||||
STATE_POLLUTANT_LABEL_CO = "co"
|
||||
STATE_POLLUTANT_LABEL_N2 = "n2"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u0397 \u03c4\u03bf\u03c0\u03bf\u03b8\u03b5\u03c3\u03af\u03b1 \u03ad\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03b4\u03b9\u03b1\u03bc\u03bf\u03c1\u03c6\u03c9\u03b8\u03b5\u03af",
|
||||
"already_configured": "\u0397 \u03c4\u03bf\u03c0\u03bf\u03b8\u03b5\u03c3\u03af\u03b1 \u03ad\u03c7\u03b5\u03b9 \u03ae\u03b4\u03b7 \u03b4\u03b9\u03b1\u03bc\u03bf\u03c1\u03c6\u03c9\u03b8\u03b5\u03af \u03ae \u03c4\u03bf Node/Pro ID \u03b5\u03af\u03bd\u03b1\u03b9 \u03ae\u03b4\u03b7 \u03ba\u03b1\u03c4\u03b1\u03c7\u03c9\u03c1\u03b7\u03bc\u03ad\u03bd\u03bf.",
|
||||
"reauth_successful": "\u039f \u03b5\u03ba \u03bd\u03ad\u03bf\u03c5 \u03ad\u03bb\u03b5\u03b3\u03c7\u03bf\u03c2 \u03c4\u03b1\u03c5\u03c4\u03cc\u03c4\u03b7\u03c4\u03b1\u03c2 \u03ae\u03c4\u03b1\u03bd \u03b5\u03c0\u03b9\u03c4\u03c5\u03c7\u03ae\u03c2"
|
||||
},
|
||||
"error": {
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"node_pro": {
|
||||
"data": {
|
||||
"password": "Slapta\u017eodis"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -50,17 +50,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"pollutant_level": {
|
||||
"state": {
|
||||
"good": "Goed",
|
||||
"hazardous": "Gevaarlijk",
|
||||
"unhealthy": "Ongezond"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Konum zaten yap\u0131land\u0131r\u0131lm\u0131\u015f",
|
||||
"already_configured": "Konum zaten yap\u0131land\u0131r\u0131lm\u0131\u015f veya Node/Pro Kimli\u011fi zaten kay\u0131tl\u0131.",
|
||||
"reauth_successful": "Yeniden kimlik do\u011frulama ba\u015far\u0131l\u0131 oldu"
|
||||
},
|
||||
"error": {
|
||||
@@ -50,36 +50,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"pollutant_label": {
|
||||
"state": {
|
||||
"co": "Karbonmonoksit",
|
||||
"n2": "Nitrojen dioksit",
|
||||
"o3": "Ozon",
|
||||
"p1": "PM10",
|
||||
"p2": "PM2.5",
|
||||
"s2": "K\u00fck\u00fcrt dioksit"
|
||||
}
|
||||
},
|
||||
"pollutant_level": {
|
||||
"state": {
|
||||
"good": "\u0130yi",
|
||||
"hazardous": "Tehlikeli",
|
||||
"moderate": "Il\u0131ml\u0131",
|
||||
"unhealthy": "Sa\u011fl\u0131ks\u0131z",
|
||||
"unhealthy_sensitive": "Hassas gruplar i\u00e7in sa\u011fl\u0131ks\u0131z",
|
||||
"very_unhealthy": "\u00c7ok sa\u011fl\u0131ks\u0131z"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"airvisual_pro_migration": {
|
||||
"description": "AirVisual Pro birimleri art\u0131k kendi Ev Asistan\u0131 entegrasyonudur (AirVisual bulut API'sini kullanan orijinal AirVisual entegrasyonuna dahil edilmek yerine). ` {ip_address} ` konumunda bulunan Pro cihaz\u0131 otomatik olarak ta\u015f\u0131nd\u0131. \n\n Bu ge\u00e7i\u015fin bir par\u00e7as\u0131 olarak, Uzman\u0131n \" {old_device_id}\" olan cihaz kimli\u011fi \" {old_device_id} {new_device_id} olarak de\u011fi\u015fti. L\u00fctfen bu otomasyonlar\u0131 yeni cihaz kimli\u011fini kullanacak \u015fekilde g\u00fcncelleyin: {device_automations_string} .",
|
||||
"title": "{ip_address} art\u0131k AirVisual Pro entegrasyonunun bir par\u00e7as\u0131"
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"step": {
|
||||
"init": {
|
||||
|
||||
@@ -21,7 +21,7 @@ from homeassistant.const import (
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
Platform,
|
||||
)
|
||||
from homeassistant.core import Event, HomeAssistant
|
||||
from homeassistant.core import Event, HomeAssistant, callback
|
||||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||
from homeassistant.helpers.entity import DeviceInfo, EntityDescription
|
||||
from homeassistant.helpers.update_coordinator import (
|
||||
@@ -136,3 +136,19 @@ class AirVisualProEntity(CoordinatorEntity):
|
||||
hw_version=self.coordinator.data["status"]["system_version"],
|
||||
sw_version=self.coordinator.data["status"]["app_version"],
|
||||
)
|
||||
|
||||
@callback
|
||||
def _async_update_from_latest_data(self) -> None:
|
||||
"""Update the entity's underlying data."""
|
||||
raise NotImplementedError
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Respond to a DataUpdateCoordinator update."""
|
||||
self._async_update_from_latest_data()
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Handle entity which will be added."""
|
||||
await super().async_added_to_hass()
|
||||
self._async_update_from_latest_data()
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
"""Support for AirVisual Pro sensors."""
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
@@ -25,93 +23,78 @@ from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from . import AirVisualProData, AirVisualProEntity
|
||||
from .const import DOMAIN
|
||||
|
||||
|
||||
@dataclass
|
||||
class AirVisualProMeasurementKeyMixin:
|
||||
"""Define an entity description mixin to include a measurement key."""
|
||||
|
||||
value_fn: Callable[[dict[str, Any], dict[str, Any], dict[str, Any]], float | int]
|
||||
|
||||
|
||||
@dataclass
|
||||
class AirVisualProMeasurementDescription(
|
||||
SensorEntityDescription, AirVisualProMeasurementKeyMixin
|
||||
):
|
||||
"""Describe an AirVisual Pro sensor."""
|
||||
|
||||
SENSOR_KIND_AQI = "air_quality_index"
|
||||
SENSOR_KIND_BATTERY_LEVEL = "battery_level"
|
||||
SENSOR_KIND_CO2 = "carbon_dioxide"
|
||||
SENSOR_KIND_HUMIDITY = "humidity"
|
||||
SENSOR_KIND_PM_0_1 = "particulate_matter_0_1"
|
||||
SENSOR_KIND_PM_1_0 = "particulate_matter_1_0"
|
||||
SENSOR_KIND_PM_2_5 = "particulate_matter_2_5"
|
||||
SENSOR_KIND_SENSOR_LIFE = "sensor_life"
|
||||
SENSOR_KIND_TEMPERATURE = "temperature"
|
||||
SENSOR_KIND_VOC = "voc"
|
||||
|
||||
SENSOR_DESCRIPTIONS = (
|
||||
AirVisualProMeasurementDescription(
|
||||
key="air_quality_index",
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_AQI,
|
||||
name="Air quality index",
|
||||
device_class=SensorDeviceClass.AQI,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_fn=lambda settings, status, measurements: measurements[
|
||||
async_get_aqi_locale(settings)
|
||||
],
|
||||
),
|
||||
AirVisualProMeasurementDescription(
|
||||
key="battery_level",
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_BATTERY_LEVEL,
|
||||
name="Battery",
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value_fn=lambda settings, status, measurements: status["battery"],
|
||||
),
|
||||
AirVisualProMeasurementDescription(
|
||||
key="carbon_dioxide",
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_CO2,
|
||||
name="C02",
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_fn=lambda settings, status, measurements: measurements["co2"],
|
||||
),
|
||||
AirVisualProMeasurementDescription(
|
||||
key="humidity",
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_HUMIDITY,
|
||||
name="Humidity",
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
value_fn=lambda settings, status, measurements: measurements["humidity"],
|
||||
),
|
||||
AirVisualProMeasurementDescription(
|
||||
key="particulate_matter_0_1",
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_PM_0_1,
|
||||
name="PM 0.1",
|
||||
device_class=SensorDeviceClass.PM1,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_fn=lambda settings, status, measurements: measurements["pm0_1"],
|
||||
),
|
||||
AirVisualProMeasurementDescription(
|
||||
key="particulate_matter_1_0",
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_PM_1_0,
|
||||
name="PM 1.0",
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_fn=lambda settings, status, measurements: measurements["pm1_0"],
|
||||
),
|
||||
AirVisualProMeasurementDescription(
|
||||
key="particulate_matter_2_5",
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_PM_2_5,
|
||||
name="PM 2.5",
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_fn=lambda settings, status, measurements: measurements["pm2_5"],
|
||||
),
|
||||
AirVisualProMeasurementDescription(
|
||||
key="temperature",
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_TEMPERATURE,
|
||||
name="Temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_fn=lambda settings, status, measurements: measurements["temperature_C"],
|
||||
),
|
||||
AirVisualProMeasurementDescription(
|
||||
key="voc",
|
||||
SensorEntityDescription(
|
||||
key=SENSOR_KIND_VOC,
|
||||
name="VOC",
|
||||
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value_fn=lambda settings, status, measurements: measurements["voc"],
|
||||
),
|
||||
)
|
||||
|
||||
@@ -141,13 +124,40 @@ class AirVisualProSensor(AirVisualProEntity, SensorEntity):
|
||||
|
||||
_attr_has_entity_name = True
|
||||
|
||||
entity_description: AirVisualProMeasurementDescription
|
||||
MEASUREMENTS_KEY_TO_VALUE = {
|
||||
SENSOR_KIND_CO2: "co2",
|
||||
SENSOR_KIND_HUMIDITY: "humidity",
|
||||
SENSOR_KIND_PM_0_1: "pm0_1",
|
||||
SENSOR_KIND_PM_1_0: "pm1_0",
|
||||
SENSOR_KIND_PM_2_5: "pm2_5",
|
||||
SENSOR_KIND_TEMPERATURE: "temperature_C",
|
||||
SENSOR_KIND_VOC: "voc",
|
||||
}
|
||||
|
||||
@property
|
||||
def native_value(self) -> float | int:
|
||||
"""Return the sensor value."""
|
||||
return self.entity_description.value_fn(
|
||||
self.coordinator.data["settings"],
|
||||
self.coordinator.data["status"],
|
||||
self.coordinator.data["measurements"],
|
||||
)
|
||||
def measurements(self) -> dict[str, Any]:
|
||||
"""Define measurements data."""
|
||||
return self.coordinator.data["measurements"]
|
||||
|
||||
@property
|
||||
def settings(self) -> dict[str, Any]:
|
||||
"""Define settings data."""
|
||||
return self.coordinator.data["settings"]
|
||||
|
||||
@property
|
||||
def status(self) -> dict[str, Any]:
|
||||
"""Define status data."""
|
||||
return self.coordinator.data["status"]
|
||||
|
||||
@callback
|
||||
def _async_update_from_latest_data(self) -> None:
|
||||
"""Update the entity from the latest data."""
|
||||
if self.entity_description.key == SENSOR_KIND_AQI:
|
||||
locale = async_get_aqi_locale(self.settings)
|
||||
self._attr_native_value = self.measurements[locale]
|
||||
elif self.entity_description.key == SENSOR_KIND_BATTERY_LEVEL:
|
||||
self._attr_native_value = self.status["battery"]
|
||||
else:
|
||||
self._attr_native_value = self.measurements[
|
||||
self.MEASUREMENTS_KEY_TO_VALUE[self.entity_description.key]
|
||||
]
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"unknown": "Neo\u010dek\u00e1van\u00e1 chyba"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Apparaat is al geconfigureerd",
|
||||
"reauth_successful": "Herauthenticatie geslaagd"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Kan geen verbinding maken",
|
||||
"invalid_auth": "Ongeldige authenticatie",
|
||||
"unknown": "Onverwachte fout"
|
||||
},
|
||||
"step": {
|
||||
"reauth_confirm": {
|
||||
"data": {
|
||||
"password": "Wachtwoord"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"ip_address": "Host",
|
||||
"password": "Wachtwoord"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Dispositivo j\u00e1 est\u00e1 configurado",
|
||||
"already_configured": "O dispositivo j\u00e1 est\u00e1 configurado",
|
||||
"reauth_successful": "A reautentica\u00e7\u00e3o foi bem-sucedida"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Falha ao conectar",
|
||||
"cannot_connect": "Falhou ao conectar",
|
||||
"invalid_auth": "Autentica\u00e7\u00e3o inv\u00e1lida",
|
||||
"unknown": "Erro inesperado"
|
||||
},
|
||||
@@ -18,7 +18,7 @@
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"ip_address": "Nome do host",
|
||||
"ip_address": "Host",
|
||||
"password": "Senha"
|
||||
},
|
||||
"description": "A senha pode ser recuperada da IU do AirVisual Pro."
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Cihaz zaten yap\u0131land\u0131r\u0131lm\u0131\u015f",
|
||||
"reauth_successful": "Yeniden kimlik do\u011frulama ba\u015far\u0131l\u0131 oldu"
|
||||
},
|
||||
"error": {
|
||||
"cannot_connect": "Ba\u011flanma hatas\u0131",
|
||||
"invalid_auth": "Ge\u00e7ersiz kimlik do\u011frulama",
|
||||
"unknown": "Beklenmeyen hata"
|
||||
},
|
||||
"step": {
|
||||
"reauth_confirm": {
|
||||
"data": {
|
||||
"password": "Parola"
|
||||
},
|
||||
"description": "Parola, AirVisual Pro'nun kullan\u0131c\u0131 aray\u00fcz\u00fcnden al\u0131nabilir."
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"ip_address": "Sunucu",
|
||||
"password": "Parola"
|
||||
},
|
||||
"description": "Parola, AirVisual Pro'nun kullan\u0131c\u0131 aray\u00fcz\u00fcnden al\u0131nabilir."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"invalid_auth": "\u041d\u0435\u0434\u0456\u0439\u0441\u043d\u0430 \u0430\u0432\u0442\u0435\u043d\u0442\u0438\u0444\u0456\u043a\u0430\u0446\u0456\u044f"
|
||||
},
|
||||
"step": {
|
||||
"reauth_confirm": {
|
||||
"data": {
|
||||
"password": "\u041f\u0430\u0440\u043e\u043b\u044c"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "\u041f\u0430\u0440\u043e\u043b\u044c"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,12 +19,7 @@ from homeassistant.helpers import (
|
||||
from .const import DOMAIN
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
|
||||
PLATFORMS: list[Platform] = [
|
||||
Platform.BINARY_SENSOR,
|
||||
Platform.CLIMATE,
|
||||
Platform.SELECT,
|
||||
Platform.SENSOR,
|
||||
]
|
||||
PLATFORMS: list[Platform] = [Platform.BINARY_SENSOR, Platform.CLIMATE, Platform.SENSOR]
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@@ -45,7 +40,7 @@ async def _async_migrate_unique_ids(
|
||||
entity_unique_id = entity_entry.unique_id
|
||||
|
||||
if entity_unique_id.startswith(entry_id):
|
||||
new_unique_id = f"{unique_id}{entity_unique_id.removeprefix(entry_id)}"
|
||||
new_unique_id = f"{unique_id}{entity_unique_id[len(entry_id):]}"
|
||||
_LOGGER.debug(
|
||||
"Migrating unique_id from [%s] to [%s]",
|
||||
entity_unique_id,
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"""Support for the Airzone climate."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any, Final
|
||||
|
||||
from aioairzone.common import OperationMode
|
||||
@@ -8,6 +9,8 @@ from aioairzone.const import (
|
||||
API_MODE,
|
||||
API_ON,
|
||||
API_SET_POINT,
|
||||
API_SYSTEM_ID,
|
||||
API_ZONE_ID,
|
||||
AZD_DEMAND,
|
||||
AZD_HUMIDITY,
|
||||
AZD_MASTER,
|
||||
@@ -22,6 +25,7 @@ from aioairzone.const import (
|
||||
AZD_TEMP_UNIT,
|
||||
AZD_ZONES,
|
||||
)
|
||||
from aioairzone.exceptions import AirzoneError
|
||||
|
||||
from homeassistant.components.climate import (
|
||||
ClimateEntity,
|
||||
@@ -39,6 +43,9 @@ from .const import API_TEMPERATURE_STEP, DOMAIN, TEMP_UNIT_LIB_TO_HASS
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
from .entity import AirzoneZoneEntity
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
HVAC_ACTION_LIB_TO_HASS: Final[dict[OperationMode, HVACAction]] = {
|
||||
OperationMode.STOP: HVACAction.OFF,
|
||||
OperationMode.COOLING: HVACAction.COOLING,
|
||||
@@ -107,6 +114,23 @@ class AirzoneClimate(AirzoneZoneEntity, ClimateEntity):
|
||||
]
|
||||
self._async_update_attrs()
|
||||
|
||||
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.set_hvac_parameters(_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_turn_on(self) -> None:
|
||||
"""Turn the entity on."""
|
||||
params = {
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
"""Entity classes for the Airzone integration."""
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from aioairzone.const import (
|
||||
API_SYSTEM_ID,
|
||||
API_ZONE_ID,
|
||||
AZD_FIRMWARE,
|
||||
AZD_FULL_NAME,
|
||||
AZD_ID,
|
||||
@@ -20,10 +17,8 @@ from aioairzone.const import (
|
||||
AZD_WEBSERVER,
|
||||
AZD_ZONES,
|
||||
)
|
||||
from aioairzone.exceptions import AirzoneError
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
@@ -31,8 +26,6 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||
from .const import DOMAIN, MANUFACTURER
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class AirzoneEntity(CoordinatorEntity[AirzoneUpdateCoordinator]):
|
||||
"""Define an Airzone entity."""
|
||||
@@ -137,20 +130,3 @@ class AirzoneZoneEntity(AirzoneEntity):
|
||||
if key in zone:
|
||||
value = zone[key]
|
||||
return value
|
||||
|
||||
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.set_hvac_parameters(_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())
|
||||
|
||||
@@ -1,160 +0,0 @@
|
||||
"""Support for the Airzone sensors."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, replace
|
||||
from typing import Any, Final
|
||||
|
||||
from aioairzone.common import GrilleAngle, SleepTimeout
|
||||
from aioairzone.const import (
|
||||
API_COLD_ANGLE,
|
||||
API_HEAT_ANGLE,
|
||||
API_SLEEP,
|
||||
AZD_COLD_ANGLE,
|
||||
AZD_HEAT_ANGLE,
|
||||
AZD_NAME,
|
||||
AZD_SLEEP,
|
||||
AZD_ZONES,
|
||||
)
|
||||
|
||||
from homeassistant.components.select import SelectEntity, SelectEntityDescription
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers.entity import EntityCategory
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import AirzoneUpdateCoordinator
|
||||
from .entity import AirzoneEntity, AirzoneZoneEntity
|
||||
|
||||
|
||||
@dataclass
|
||||
class AirzoneSelectDescriptionMixin:
|
||||
"""Define an entity description mixin for select entities."""
|
||||
|
||||
api_param: str
|
||||
options_dict: dict[str, int]
|
||||
|
||||
|
||||
@dataclass
|
||||
class AirzoneSelectDescription(SelectEntityDescription, AirzoneSelectDescriptionMixin):
|
||||
"""Class to describe an Airzone select entity."""
|
||||
|
||||
|
||||
GRILLE_ANGLE_DICT: Final[dict[str, int]] = {
|
||||
"90º": GrilleAngle.DEG_90,
|
||||
"50º": GrilleAngle.DEG_50,
|
||||
"45º": GrilleAngle.DEG_45,
|
||||
"40º": GrilleAngle.DEG_40,
|
||||
}
|
||||
|
||||
SLEEP_DICT: Final[dict[str, int]] = {
|
||||
"Off": SleepTimeout.SLEEP_OFF,
|
||||
"30m": SleepTimeout.SLEEP_30,
|
||||
"60m": SleepTimeout.SLEEP_60,
|
||||
"90m": SleepTimeout.SLEEP_90,
|
||||
}
|
||||
|
||||
|
||||
ZONE_SELECT_TYPES: Final[tuple[AirzoneSelectDescription, ...]] = (
|
||||
AirzoneSelectDescription(
|
||||
api_param=API_COLD_ANGLE,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
key=AZD_COLD_ANGLE,
|
||||
name="Cold Angle",
|
||||
options_dict=GRILLE_ANGLE_DICT,
|
||||
),
|
||||
AirzoneSelectDescription(
|
||||
api_param=API_HEAT_ANGLE,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
key=AZD_HEAT_ANGLE,
|
||||
name="Heat Angle",
|
||||
options_dict=GRILLE_ANGLE_DICT,
|
||||
),
|
||||
AirzoneSelectDescription(
|
||||
api_param=API_SLEEP,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
key=AZD_SLEEP,
|
||||
name="Sleep",
|
||||
options_dict=SLEEP_DICT,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
async def async_setup_entry(
|
||||
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
|
||||
) -> None:
|
||||
"""Add Airzone sensors from a config_entry."""
|
||||
coordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
|
||||
entities: list[AirzoneBaseSelect] = []
|
||||
|
||||
for system_zone_id, zone_data in coordinator.data[AZD_ZONES].items():
|
||||
for description in ZONE_SELECT_TYPES:
|
||||
if description.key in zone_data:
|
||||
_desc = replace(
|
||||
description,
|
||||
options=list(description.options_dict.keys()),
|
||||
)
|
||||
entities.append(
|
||||
AirzoneZoneSelect(
|
||||
coordinator,
|
||||
_desc,
|
||||
entry,
|
||||
system_zone_id,
|
||||
zone_data,
|
||||
)
|
||||
)
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
class AirzoneBaseSelect(AirzoneEntity, SelectEntity):
|
||||
"""Define an Airzone select."""
|
||||
|
||||
entity_description: AirzoneSelectDescription
|
||||
values_dict: dict[int, str]
|
||||
|
||||
@callback
|
||||
def _handle_coordinator_update(self) -> None:
|
||||
"""Update attributes when the coordinator updates."""
|
||||
self._async_update_attrs()
|
||||
super()._handle_coordinator_update()
|
||||
|
||||
def _get_current_option(self) -> str | None:
|
||||
value = self.get_airzone_value(self.entity_description.key)
|
||||
return self.values_dict.get(value)
|
||||
|
||||
@callback
|
||||
def _async_update_attrs(self) -> None:
|
||||
"""Update select attributes."""
|
||||
self._attr_current_option = self._get_current_option()
|
||||
|
||||
|
||||
class AirzoneZoneSelect(AirzoneZoneEntity, AirzoneBaseSelect):
|
||||
"""Define an Airzone Zone select."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: AirzoneUpdateCoordinator,
|
||||
description: AirzoneSelectDescription,
|
||||
entry: ConfigEntry,
|
||||
system_zone_id: str,
|
||||
zone_data: dict[str, Any],
|
||||
) -> 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"{self._attr_unique_id}_{system_zone_id}_{description.key}"
|
||||
)
|
||||
self.entity_description = description
|
||||
self.values_dict = {v: k for k, v in description.options_dict.items()}
|
||||
|
||||
self._async_update_attrs()
|
||||
|
||||
async def async_select_option(self, option: str) -> None:
|
||||
"""Change the selected option."""
|
||||
param = self.entity_description.api_param
|
||||
value = self.entity_description.options_dict[option]
|
||||
await self._async_update_hvac_params({param: value})
|
||||
@@ -10,7 +10,6 @@
|
||||
"step": {
|
||||
"discovered_connection": {
|
||||
"data": {
|
||||
"host": "Host",
|
||||
"id": "Systeem ID",
|
||||
"port": "Poort"
|
||||
}
|
||||
|
||||
@@ -8,17 +8,9 @@
|
||||
"invalid_system_id": "Ge\u00e7ersiz Airzone Sistem Kimli\u011fi"
|
||||
},
|
||||
"step": {
|
||||
"discovered_connection": {
|
||||
"data": {
|
||||
"host": "Sunucu",
|
||||
"id": "Sistem ID",
|
||||
"port": "Port"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "Sunucu",
|
||||
"id": "Sistem ID",
|
||||
"port": "Port"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@ import logging
|
||||
from typing import Final
|
||||
|
||||
from AIOAladdinConnect import AladdinConnectClient
|
||||
import AIOAladdinConnect.session_manager as Aladdin
|
||||
from aiohttp import ClientError
|
||||
from AIOAladdinConnect.session_manager import InvalidPasswordError
|
||||
from aiohttp import ClientConnectionError
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform
|
||||
@@ -29,9 +29,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||
)
|
||||
try:
|
||||
await acc.login()
|
||||
except (ClientError, asyncio.TimeoutError, Aladdin.ConnectionError) as ex:
|
||||
except (ClientConnectionError, asyncio.TimeoutError) as ex:
|
||||
raise ConfigEntryNotReady("Can not connect to host") from ex
|
||||
except Aladdin.InvalidPasswordError as ex:
|
||||
except InvalidPasswordError as ex:
|
||||
raise ConfigEntryAuthFailed("Incorrect Password") from ex
|
||||
|
||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = acc
|
||||
|
||||
@@ -7,8 +7,8 @@ import logging
|
||||
from typing import Any
|
||||
|
||||
from AIOAladdinConnect import AladdinConnectClient
|
||||
import AIOAladdinConnect.session_manager as Aladdin
|
||||
from aiohttp.client_exceptions import ClientError
|
||||
from AIOAladdinConnect.session_manager import InvalidPasswordError
|
||||
from aiohttp.client_exceptions import ClientConnectionError
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant import config_entries
|
||||
@@ -45,10 +45,10 @@ async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> None:
|
||||
)
|
||||
try:
|
||||
await acc.login()
|
||||
except (ClientError, asyncio.TimeoutError, Aladdin.ConnectionError) as ex:
|
||||
except (ClientConnectionError, asyncio.TimeoutError) as ex:
|
||||
raise ex
|
||||
|
||||
except Aladdin.InvalidPasswordError as ex:
|
||||
except InvalidPasswordError as ex:
|
||||
raise InvalidAuth from ex
|
||||
|
||||
|
||||
@@ -84,7 +84,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
except InvalidAuth:
|
||||
errors["base"] = "invalid_auth"
|
||||
|
||||
except (ClientError, asyncio.TimeoutError, Aladdin.ConnectionError):
|
||||
except (ClientConnectionError, asyncio.TimeoutError):
|
||||
errors["base"] = "cannot_connect"
|
||||
|
||||
else:
|
||||
@@ -121,7 +121,7 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
except InvalidAuth:
|
||||
errors["base"] = "invalid_auth"
|
||||
|
||||
except (ClientError, asyncio.TimeoutError, Aladdin.ConnectionError):
|
||||
except (ClientConnectionError, asyncio.TimeoutError):
|
||||
errors["base"] = "cannot_connect"
|
||||
|
||||
else:
|
||||
|
||||
@@ -91,27 +91,31 @@ class AladdinDevice(CoverEntity):
|
||||
self._name = device["name"]
|
||||
self._serial = device["serial"]
|
||||
self._model = device["model"]
|
||||
self._attr_unique_id = f"{self._device_id}-{self._number}"
|
||||
self._attr_has_entity_name = True
|
||||
|
||||
self._attr_device_info = DeviceInfo(
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo | None:
|
||||
"""Device information for Aladdin Connect cover."""
|
||||
return DeviceInfo(
|
||||
identifiers={(DOMAIN, f"{self._device_id}-{self._number}")},
|
||||
name=self._name,
|
||||
manufacturer="Overhead Door",
|
||||
model=self._model,
|
||||
)
|
||||
self._attr_has_entity_name = True
|
||||
self._attr_unique_id = f"{self._device_id}-{self._number}"
|
||||
|
||||
async def async_added_to_hass(self) -> None:
|
||||
"""Connect Aladdin Connect to the cloud."""
|
||||
|
||||
self._acc.register_callback(
|
||||
self.async_write_ha_state, self._serial, self._number
|
||||
)
|
||||
async def update_callback() -> None:
|
||||
"""Schedule a state update."""
|
||||
self.async_write_ha_state()
|
||||
|
||||
self._acc.register_callback(update_callback, self._serial, self._number)
|
||||
await self._acc.get_doors(self._serial)
|
||||
|
||||
async def async_will_remove_from_hass(self) -> None:
|
||||
"""Close Aladdin Connect before removing."""
|
||||
self._acc.unregister_callback(self._serial, self._number)
|
||||
await self._acc.close()
|
||||
|
||||
async def async_close_cover(self, **kwargs: Any) -> None:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"domain": "aladdin_connect",
|
||||
"name": "Aladdin Connect",
|
||||
"documentation": "https://www.home-assistant.io/integrations/aladdin_connect",
|
||||
"requirements": ["AIOAladdinConnect==0.1.52"],
|
||||
"requirements": ["AIOAladdinConnect==0.1.48"],
|
||||
"codeowners": ["@mkmer"],
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["aladdin_connect"],
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"reauth_confirm": {
|
||||
"data": {
|
||||
"password": "\u041f\u0430\u0440\u043e\u043b\u044c"
|
||||
}
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "\u041f\u0430\u0440\u043e\u043b\u044c",
|
||||
"username": "\u0406\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,44 +1,13 @@
|
||||
{
|
||||
"device_automation": {
|
||||
"action_type": {
|
||||
"arm_away": "U\u017erakinti {entity_name}",
|
||||
"arm_home": "U\u017erakinti {entity_name} - Namie",
|
||||
"arm_night": "U\u017erakinti {entity_name} - Naktin\u0117 apsauga",
|
||||
"arm_vacation": "U\u017erakinti {entity_name} atostog\u0173 re\u017eime",
|
||||
"disarm": "I\u0161jungti {entity_name}",
|
||||
"trigger": "Suaktyvinti {entity_name}"
|
||||
},
|
||||
"condition_type": {
|
||||
"is_armed_away": "{entity_name} yra u\u017erakinta",
|
||||
"is_armed_home": "{entity_name} yra u\u017erakinta nam\u0173 re\u017eime",
|
||||
"is_armed_night": "{entity_name} u\u017erakinta naktin\u0117 apsauga",
|
||||
"is_armed_vacation": "{entity_name} u\u017erakinta atostog\u0173 re\u017eime",
|
||||
"is_disarmed": "{entity_name} i\u0161jungta",
|
||||
"is_triggered": "{entity_name} suveik\u0117"
|
||||
},
|
||||
"trigger_type": {
|
||||
"armed_away": "{entity_name} u\u017erakinta",
|
||||
"armed_home": "{entity_name} u\u017erakinta - Namie",
|
||||
"armed_night": "{entity_name} u\u017erakinta - Naktin\u0117 apsauga",
|
||||
"armed_vacation": "{entity_name} u\u017erakinta - atostog\u0173 re\u017eime",
|
||||
"disarmed": "{entity_name} i\u0161jungta",
|
||||
"triggered": "{entity_name} suveik\u0117"
|
||||
}
|
||||
},
|
||||
"state": {
|
||||
"_": {
|
||||
"armed": "U\u017erakinta",
|
||||
"armed_away": "U\u017erakinta",
|
||||
"armed_custom_bypass": "U\u017erakinta su ap\u0117jimu",
|
||||
"armed_home": "\u012ejungta - Namie",
|
||||
"armed_night": "Naktin\u0117 apsauga",
|
||||
"armed_vacation": "U\u017erakinta - atostog\u0173 re\u017eime",
|
||||
"arming": "U\u017erakinama",
|
||||
"armed_home": "Nam\u0173 apsauga \u012fjungta",
|
||||
"arming": "Saugojimo re\u017eimo \u012fjungimas",
|
||||
"disarmed": "Atrakinta",
|
||||
"disarming": "Saugojimo re\u017eimo i\u0161jungimas",
|
||||
"pending": "Laukiama",
|
||||
"triggered": "Aktyvinta"
|
||||
}
|
||||
},
|
||||
"title": "Signalizacijos valdymo pultas"
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "\u012erenginys jau sukonfig\u016bruotas"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"state": {
|
||||
"_": {
|
||||
"idle": "Laukiama"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
{
|
||||
"state": {
|
||||
"_": {
|
||||
"idle": "Bo\u015fta",
|
||||
"off": "Onayland\u0131",
|
||||
"on": "Etkin"
|
||||
}
|
||||
},
|
||||
"title": "Uyar\u0131"
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"state": {
|
||||
"_": {
|
||||
"idle": "\u0411\u0435\u0437\u0434\u0456\u044f\u043b\u044c\u043d\u0456\u0441\u0442\u044c"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"auth": {
|
||||
"description": "Pra\u0161ome sekti \u0161ia [nuoroda]({authorization_url}) ir **leisti** prieig\u0105 prie savo \"Ambiclimate\" paskyros, tada gr\u012f\u017ekite ir paspauskite **Pateikti** toliau.\n(\u012esitikinkite, kad nurodytas gr\u012f\u017etamojo ry\u0161io URL yra {cb_url})"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"username": "\u0406\u043c'\u044f \u043a\u043e\u0440\u0438\u0441\u0442\u0443\u0432\u0430\u0447\u0430"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
"""Virtual integration: ANWB Energie."""
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"domain": "anwb_energie",
|
||||
"name": "ANWB Energie",
|
||||
"integration_type": "virtual",
|
||||
"supported_by": "energyzero"
|
||||
}
|
||||
@@ -62,7 +62,7 @@ class APCUPSdData:
|
||||
"""Initialize the data object."""
|
||||
self._host = host
|
||||
self._port = port
|
||||
self.status: dict[str, str] = {}
|
||||
self.status: dict[str, Any] = {}
|
||||
|
||||
@property
|
||||
def name(self) -> str | None:
|
||||
@@ -100,7 +100,7 @@ class APCUPSdData:
|
||||
return self.status.get("STATFLAG")
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def update(self, **kwargs: Any) -> None:
|
||||
def update(self, **kwargs):
|
||||
"""Fetch the latest status from APCUPSd.
|
||||
|
||||
Note that the result dict uses upper case for each resource, where our
|
||||
|
||||
@@ -65,15 +65,8 @@ class OnlineStatus(BinarySensorEntity):
|
||||
|
||||
def update(self) -> None:
|
||||
"""Get the status report from APCUPSd and set this entity's state."""
|
||||
try:
|
||||
self._data_service.update()
|
||||
except OSError as ex:
|
||||
if self._attr_available:
|
||||
self._attr_available = False
|
||||
_LOGGER.exception("Got exception while fetching state: %s", ex)
|
||||
return
|
||||
self._data_service.update()
|
||||
|
||||
self._attr_available = True
|
||||
key = self.entity_description.key.upper()
|
||||
if key not in self._data_service.status:
|
||||
self._attr_is_on = None
|
||||
|
||||
@@ -9,7 +9,6 @@ from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorEntityDescription,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import (
|
||||
@@ -40,9 +39,6 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
||||
key="ambtemp",
|
||||
name="UPS Ambient Temperature",
|
||||
icon="mdi:thermometer",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"apc": SensorEntityDescription(
|
||||
key="apc",
|
||||
@@ -76,15 +72,12 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
||||
name="UPS Battery Voltage",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"bcharge": SensorEntityDescription(
|
||||
key="bcharge",
|
||||
name="UPS Battery",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
icon="mdi:battery",
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"cable": SensorEntityDescription(
|
||||
key="cable",
|
||||
@@ -96,7 +89,6 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
||||
key="cumonbatt",
|
||||
name="UPS Total Time on Battery",
|
||||
icon="mdi:timer-outline",
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
"date": SensorEntityDescription(
|
||||
key="date",
|
||||
@@ -163,16 +155,13 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
||||
key="humidity",
|
||||
name="UPS Ambient Humidity",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
icon="mdi:water-percent",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"itemp": SensorEntityDescription(
|
||||
key="itemp",
|
||||
name="UPS Internal Temperature",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"laststest": SensorEntityDescription(
|
||||
key="laststest",
|
||||
@@ -195,21 +184,18 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
||||
name="UPS Line Frequency",
|
||||
native_unit_of_measurement=UnitOfFrequency.HERTZ,
|
||||
device_class=SensorDeviceClass.FREQUENCY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"linev": SensorEntityDescription(
|
||||
key="linev",
|
||||
name="UPS Input Voltage",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"loadpct": SensorEntityDescription(
|
||||
key="loadpct",
|
||||
name="UPS Load",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
icon="mdi:gauge",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"loadapnt": SensorEntityDescription(
|
||||
key="loadapnt",
|
||||
@@ -302,21 +288,18 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
||||
key="numxfers",
|
||||
name="UPS Transfer Count",
|
||||
icon="mdi:counter",
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
"outcurnt": SensorEntityDescription(
|
||||
key="outcurnt",
|
||||
name="UPS Output Current",
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"outputv": SensorEntityDescription(
|
||||
key="outputv",
|
||||
name="UPS Output Voltage",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"reg1": SensorEntityDescription(
|
||||
key="reg1",
|
||||
@@ -379,19 +362,16 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
||||
key="stesti",
|
||||
name="UPS Self Test Interval",
|
||||
icon="mdi:information-outline",
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
"timeleft": SensorEntityDescription(
|
||||
key="timeleft",
|
||||
name="UPS Time Left",
|
||||
icon="mdi:clock-alert",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
"tonbatt": SensorEntityDescription(
|
||||
key="tonbatt",
|
||||
name="UPS Time on Battery",
|
||||
icon="mdi:timer-outline",
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
"upsmode": SensorEntityDescription(
|
||||
key="upsmode",
|
||||
@@ -465,7 +445,7 @@ async def async_setup_entry(
|
||||
async_add_entities(entities, update_before_add=True)
|
||||
|
||||
|
||||
def infer_unit(value: str) -> tuple[str, str | None]:
|
||||
def infer_unit(value):
|
||||
"""If the value ends with any of the units from ALL_UNITS.
|
||||
|
||||
Split the unit off the end of the value and return the value, unit tuple
|
||||
@@ -474,7 +454,7 @@ def infer_unit(value: str) -> tuple[str, str | None]:
|
||||
|
||||
for unit in ALL_UNITS:
|
||||
if value.endswith(unit):
|
||||
return value.removesuffix(unit), INFERRED_UNITS.get(unit, unit.strip())
|
||||
return value[: -len(unit)], INFERRED_UNITS.get(unit, unit.strip())
|
||||
return value, None
|
||||
|
||||
|
||||
@@ -503,15 +483,8 @@ class APCUPSdSensor(SensorEntity):
|
||||
|
||||
def update(self) -> None:
|
||||
"""Get the latest status and use it to update our sensor state."""
|
||||
try:
|
||||
self._data_service.update()
|
||||
except OSError as ex:
|
||||
if self._attr_available:
|
||||
self._attr_available = False
|
||||
_LOGGER.exception("Got exception while fetching state: %s", ex)
|
||||
return
|
||||
self._data_service.update()
|
||||
|
||||
self._attr_available = True
|
||||
key = self.entity_description.key.upper()
|
||||
if key not in self._data_service.status:
|
||||
self._attr_native_value = None
|
||||
|
||||
@@ -15,10 +15,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"deprecated_yaml": {
|
||||
"title": "De APC UPS Daemon YAML-configuratie wordt verwijderd."
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -344,7 +344,12 @@ class AppleTVManager:
|
||||
ATTR_MANUFACTURER: "Apple",
|
||||
ATTR_NAME: self.config_entry.data[CONF_NAME],
|
||||
}
|
||||
attrs[ATTR_SUGGESTED_AREA] = attrs[ATTR_NAME].removesuffix(f" {DEFAULT_NAME}")
|
||||
|
||||
area = attrs[ATTR_NAME]
|
||||
name_trailer = f" {DEFAULT_NAME}"
|
||||
if area.endswith(name_trailer):
|
||||
area = area[: -len(name_trailer)]
|
||||
attrs[ATTR_SUGGESTED_AREA] = area
|
||||
|
||||
if self.atv:
|
||||
dev_info = self.atv.device_info
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/aranet",
|
||||
"requirements": ["aranet4==2.1.3"],
|
||||
"dependencies": ["bluetooth_adapters"],
|
||||
"dependencies": ["bluetooth"],
|
||||
"codeowners": ["@aschmitz"],
|
||||
"iot_class": "local_push",
|
||||
"integration_type": "device",
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Az eszk\u00f6z m\u00e1r konfigur\u00e1lva van",
|
||||
"integrations_diabled": "Ezen az eszk\u00f6z\u00f6n nincs enged\u00e9lyezve az integr\u00e1ci\u00f3. K\u00e9rem, enged\u00e9lyezze az okosotthon-integr\u00e1ci\u00f3kat az alkalmaz\u00e1s seg\u00edts\u00e9g\u00e9vel, \u00e9s pr\u00f3b\u00e1lja meg \u00fajra.",
|
||||
"integrations_diabled": "Ezen az eszk\u00f6z\u00f6n nincs enged\u00e9lyezve az integr\u00e1ci\u00f3. K\u00e9rj\u00fck, enged\u00e9lyezze az okosotthon-integr\u00e1ci\u00f3kat az alkalmaz\u00e1s seg\u00edts\u00e9g\u00e9vel, \u00e9s pr\u00f3b\u00e1lja meg \u00fajra.",
|
||||
"no_devices_found": "Nem tal\u00e1lhat\u00f3 konfigur\u00e1latlan Aranet eszk\u00f6z.",
|
||||
"outdated_version": "Ez az eszk\u00f6z elavult firmware-t haszn\u00e1l. K\u00e9rem, friss\u00edtse legal\u00e1bb 1.2.0-s verzi\u00f3ra, \u00e9s pr\u00f3b\u00e1lja \u00fajra."
|
||||
"outdated_version": "Ez az eszk\u00f6z elavult firmware-t haszn\u00e1l. K\u00e9rj\u00fck, friss\u00edtse legal\u00e1bb 1.2.0-s verzi\u00f3ra, \u00e9s pr\u00f3b\u00e1lja \u00fajra."
|
||||
},
|
||||
"error": {
|
||||
"unknown": "V\u00e1ratlan hiba t\u00f6rt\u00e9nt"
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Apparaat is al geconfigureerd",
|
||||
"no_devices_found": "Geen niet-geconfigureerde Aranet apparaten gevonden.",
|
||||
"outdated_version": "Dit apparaat gebruikt verouderde firmware. Werk het bij naar minstens v1.2.0 en probeer het opnieuw."
|
||||
"already_configured": "Apparaat is al geconfigureerd"
|
||||
},
|
||||
"error": {
|
||||
"unknown": "Onverwachte fout"
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Cihaz zaten yap\u0131land\u0131r\u0131lm\u0131\u015f",
|
||||
"integrations_diabled": "Bu cihazda entegrasyon etkinle\u015ftirilmemi\u015f. L\u00fctfen uygulamay\u0131 kullanarak ak\u0131ll\u0131 ev entegrasyonlar\u0131n\u0131 etkinle\u015ftirin ve tekrar deneyin.",
|
||||
"no_devices_found": "Yap\u0131land\u0131r\u0131lmam\u0131\u015f Aranet cihaz\u0131 bulunamad\u0131.",
|
||||
"outdated_version": "Bu cihaz eski \u00fcretici yaz\u0131l\u0131m\u0131 kullan\u0131yor. L\u00fctfen en az v1.2.0 s\u00fcr\u00fcm\u00fcne g\u00fcncelleyin ve tekrar deneyin."
|
||||
},
|
||||
"error": {
|
||||
"unknown": "Beklenmeyen hata"
|
||||
},
|
||||
"flow_title": "{name}",
|
||||
"step": {
|
||||
"bluetooth_confirm": {
|
||||
"description": "{name} 'i kurmak istiyor musunuz?"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"address": "Cihaz"
|
||||
},
|
||||
"description": "Kurmak i\u00e7in bir cihaz se\u00e7in"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user