mirror of
https://github.com/home-assistant/core.git
synced 2025-07-31 09:17:10 +00:00
Merge pull request #61501 from home-assistant/rc
This commit is contained in:
commit
604a2ac327
120
.core_files.yaml
Normal file
120
.core_files.yaml
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
# Defines a list of files that are part of main core of Home Assistant.
|
||||||
|
# Changes to these files/filters define how our CI test suite is ran.
|
||||||
|
core: &core
|
||||||
|
- homeassistant/*.py
|
||||||
|
- homeassistant/auth/**
|
||||||
|
- homeassistant/helpers/*
|
||||||
|
- homeassistant/package_constraints.txt
|
||||||
|
- homeassistant/util/*
|
||||||
|
- pyproject.yaml
|
||||||
|
- requirements.txt
|
||||||
|
- setup.cfg
|
||||||
|
|
||||||
|
# Our base platforms, that are used by other integrations
|
||||||
|
base_platforms: &base_platforms
|
||||||
|
- homeassistant/components/air_quality/*
|
||||||
|
- homeassistant/components/alarm_control_panel/*
|
||||||
|
- homeassistant/components/binary_sensor/*
|
||||||
|
- homeassistant/components/button/*
|
||||||
|
- homeassistant/components/calendar/*
|
||||||
|
- homeassistant/components/camera/*
|
||||||
|
- homeassistant/components/climate/*
|
||||||
|
- homeassistant/components/cover/*
|
||||||
|
- homeassistant/components/device_tracker/*
|
||||||
|
- homeassistant/components/fan/*
|
||||||
|
- homeassistant/components/geo_location/*
|
||||||
|
- homeassistant/components/humidifier/*
|
||||||
|
- homeassistant/components/image_processing/*
|
||||||
|
- homeassistant/components/light/*
|
||||||
|
- homeassistant/components/lock/*
|
||||||
|
- homeassistant/components/media_player/*
|
||||||
|
- homeassistant/components/notify/*
|
||||||
|
- homeassistant/components/number/*
|
||||||
|
- homeassistant/components/remote/*
|
||||||
|
- homeassistant/components/scene/*
|
||||||
|
- homeassistant/components/select/*
|
||||||
|
- homeassistant/components/sensor/*
|
||||||
|
- homeassistant/components/siren/*
|
||||||
|
- homeassistant/components/stt/*
|
||||||
|
- homeassistant/components/switch/*
|
||||||
|
- homeassistant/components/tts/*
|
||||||
|
- homeassistant/components/vacuum/*
|
||||||
|
- homeassistant/components/water_heater/*
|
||||||
|
- homeassistant/components/weather/*
|
||||||
|
|
||||||
|
# Extra components that trigger the full suite
|
||||||
|
components: &components
|
||||||
|
- homeassistant/components/alert/*
|
||||||
|
- homeassistant/components/alexa/*
|
||||||
|
- homeassistant/components/auth/*
|
||||||
|
- homeassistant/components/automation/*
|
||||||
|
- homeassistant/components/cloud/*
|
||||||
|
- homeassistant/components/config/*
|
||||||
|
- homeassistant/components/configurator/*
|
||||||
|
- homeassistant/components/conversation/*
|
||||||
|
- homeassistant/components/demo/*
|
||||||
|
- homeassistant/components/device_automation/*
|
||||||
|
- homeassistant/components/dhcp/*
|
||||||
|
- homeassistant/components/discovery/*
|
||||||
|
- homeassistant/components/energy/*
|
||||||
|
- homeassistant/components/ffmpeg/*
|
||||||
|
- homeassistant/components/frontend/*
|
||||||
|
- homeassistant/components/google_assistant/*
|
||||||
|
- homeassistant/components/group/*
|
||||||
|
- homeassistant/components/hassio/*
|
||||||
|
- homeassistant/components/homeassistant/**
|
||||||
|
- homeassistant/components/image/*
|
||||||
|
- homeassistant/components/input_boolean/*
|
||||||
|
- homeassistant/components/input_datetime/*
|
||||||
|
- homeassistant/components/input_number/*
|
||||||
|
- homeassistant/components/input_select/*
|
||||||
|
- homeassistant/components/input_text/*
|
||||||
|
- homeassistant/components/logbook/*
|
||||||
|
- homeassistant/components/logger/*
|
||||||
|
- homeassistant/components/lovelace/*
|
||||||
|
- homeassistant/components/media_source/*
|
||||||
|
- homeassistant/components/mqtt/*
|
||||||
|
- homeassistant/components/network/*
|
||||||
|
- homeassistant/components/onboarding/*
|
||||||
|
- homeassistant/components/otp/*
|
||||||
|
- homeassistant/components/persistent_notification/*
|
||||||
|
- homeassistant/components/person/*
|
||||||
|
- homeassistant/components/recorder/*
|
||||||
|
- homeassistant/components/safe_mode/*
|
||||||
|
- homeassistant/components/script/*
|
||||||
|
- homeassistant/components/shopping_list/*
|
||||||
|
- homeassistant/components/ssdp/*
|
||||||
|
- homeassistant/components/stream/*
|
||||||
|
- homeassistant/components/sun/*
|
||||||
|
- homeassistant/components/system_health/*
|
||||||
|
- homeassistant/components/tag/*
|
||||||
|
- homeassistant/components/template/*
|
||||||
|
- homeassistant/components/timer/*
|
||||||
|
- homeassistant/components/usb/*
|
||||||
|
- homeassistant/components/webhook/*
|
||||||
|
- homeassistant/components/websocket_api/*
|
||||||
|
- homeassistant/components/zeroconf/*
|
||||||
|
- homeassistant/components/zone/*
|
||||||
|
|
||||||
|
# Testing related files that affect the whole test/linting suite
|
||||||
|
tests: &tests
|
||||||
|
- codecov.yaml
|
||||||
|
- requirements_test_pre_commit.txt
|
||||||
|
- requirements_test.txt
|
||||||
|
- tests/common.py
|
||||||
|
- tests/conftest.py
|
||||||
|
- tests/ignore_uncaught_exceptions.py
|
||||||
|
- tests/mock/*
|
||||||
|
- tests/test_util/*
|
||||||
|
- tests/testing_config/**
|
||||||
|
|
||||||
|
other: &other
|
||||||
|
- .github/workflows/*
|
||||||
|
- homeassistant/scripts/**
|
||||||
|
|
||||||
|
any:
|
||||||
|
- *base_platforms
|
||||||
|
- *components
|
||||||
|
- *core
|
||||||
|
- *other
|
||||||
|
- *tests
|
64
.coveragerc
64
.coveragerc
@ -90,6 +90,8 @@ omit =
|
|||||||
homeassistant/components/azure_devops/sensor.py
|
homeassistant/components/azure_devops/sensor.py
|
||||||
homeassistant/components/azure_service_bus/*
|
homeassistant/components/azure_service_bus/*
|
||||||
homeassistant/components/baidu/tts.py
|
homeassistant/components/baidu/tts.py
|
||||||
|
homeassistant/components/balboa/__init__.py
|
||||||
|
homeassistant/components/balboa/entity.py
|
||||||
homeassistant/components/beewi_smartclim/sensor.py
|
homeassistant/components/beewi_smartclim/sensor.py
|
||||||
homeassistant/components/bbb_gpio/*
|
homeassistant/components/bbb_gpio/*
|
||||||
homeassistant/components/bbox/device_tracker.py
|
homeassistant/components/bbox/device_tracker.py
|
||||||
@ -123,6 +125,7 @@ omit =
|
|||||||
homeassistant/components/bosch_shc/__init__.py
|
homeassistant/components/bosch_shc/__init__.py
|
||||||
homeassistant/components/bosch_shc/binary_sensor.py
|
homeassistant/components/bosch_shc/binary_sensor.py
|
||||||
homeassistant/components/bosch_shc/const.py
|
homeassistant/components/bosch_shc/const.py
|
||||||
|
homeassistant/components/bosch_shc/cover.py
|
||||||
homeassistant/components/bosch_shc/entity.py
|
homeassistant/components/bosch_shc/entity.py
|
||||||
homeassistant/components/bosch_shc/sensor.py
|
homeassistant/components/bosch_shc/sensor.py
|
||||||
homeassistant/components/braviatv/__init__.py
|
homeassistant/components/braviatv/__init__.py
|
||||||
@ -137,7 +140,9 @@ omit =
|
|||||||
homeassistant/components/broadlink/updater.py
|
homeassistant/components/broadlink/updater.py
|
||||||
homeassistant/components/brottsplatskartan/sensor.py
|
homeassistant/components/brottsplatskartan/sensor.py
|
||||||
homeassistant/components/browser/*
|
homeassistant/components/browser/*
|
||||||
|
homeassistant/components/brunt/__init__.py
|
||||||
homeassistant/components/brunt/cover.py
|
homeassistant/components/brunt/cover.py
|
||||||
|
homeassistant/components/brunt/const.py
|
||||||
homeassistant/components/bsblan/climate.py
|
homeassistant/components/bsblan/climate.py
|
||||||
homeassistant/components/bt_home_hub_5/device_tracker.py
|
homeassistant/components/bt_home_hub_5/device_tracker.py
|
||||||
homeassistant/components/bt_smarthub/device_tracker.py
|
homeassistant/components/bt_smarthub/device_tracker.py
|
||||||
@ -281,6 +286,7 @@ omit =
|
|||||||
homeassistant/components/eq3btsmart/climate.py
|
homeassistant/components/eq3btsmart/climate.py
|
||||||
homeassistant/components/esphome/__init__.py
|
homeassistant/components/esphome/__init__.py
|
||||||
homeassistant/components/esphome/binary_sensor.py
|
homeassistant/components/esphome/binary_sensor.py
|
||||||
|
homeassistant/components/esphome/button.py
|
||||||
homeassistant/components/esphome/camera.py
|
homeassistant/components/esphome/camera.py
|
||||||
homeassistant/components/esphome/climate.py
|
homeassistant/components/esphome/climate.py
|
||||||
homeassistant/components/esphome/cover.py
|
homeassistant/components/esphome/cover.py
|
||||||
@ -369,7 +375,6 @@ omit =
|
|||||||
homeassistant/components/fritzbox_callmonitor/const.py
|
homeassistant/components/fritzbox_callmonitor/const.py
|
||||||
homeassistant/components/fritzbox_callmonitor/base.py
|
homeassistant/components/fritzbox_callmonitor/base.py
|
||||||
homeassistant/components/fritzbox_callmonitor/sensor.py
|
homeassistant/components/fritzbox_callmonitor/sensor.py
|
||||||
homeassistant/components/fronius/sensor.py
|
|
||||||
homeassistant/components/frontier_silicon/media_player.py
|
homeassistant/components/frontier_silicon/media_player.py
|
||||||
homeassistant/components/futurenow/light.py
|
homeassistant/components/futurenow/light.py
|
||||||
homeassistant/components/garadget/cover.py
|
homeassistant/components/garadget/cover.py
|
||||||
@ -386,10 +391,6 @@ omit =
|
|||||||
homeassistant/components/glances/sensor.py
|
homeassistant/components/glances/sensor.py
|
||||||
homeassistant/components/gntp/notify.py
|
homeassistant/components/gntp/notify.py
|
||||||
homeassistant/components/goalfeed/*
|
homeassistant/components/goalfeed/*
|
||||||
homeassistant/components/goalzero/__init__.py
|
|
||||||
homeassistant/components/goalzero/binary_sensor.py
|
|
||||||
homeassistant/components/goalzero/sensor.py
|
|
||||||
homeassistant/components/goalzero/switch.py
|
|
||||||
homeassistant/components/google/*
|
homeassistant/components/google/*
|
||||||
homeassistant/components/google_cloud/tts.py
|
homeassistant/components/google_cloud/tts.py
|
||||||
homeassistant/components/google_maps/device_tracker.py
|
homeassistant/components/google_maps/device_tracker.py
|
||||||
@ -399,8 +400,6 @@ omit =
|
|||||||
homeassistant/components/google_travel_time/sensor.py
|
homeassistant/components/google_travel_time/sensor.py
|
||||||
homeassistant/components/gpmdp/media_player.py
|
homeassistant/components/gpmdp/media_player.py
|
||||||
homeassistant/components/gpsd/sensor.py
|
homeassistant/components/gpsd/sensor.py
|
||||||
homeassistant/components/greeneye_monitor/*
|
|
||||||
homeassistant/components/greeneye_monitor/sensor.py
|
|
||||||
homeassistant/components/greenwave/light.py
|
homeassistant/components/greenwave/light.py
|
||||||
homeassistant/components/group/notify.py
|
homeassistant/components/group/notify.py
|
||||||
homeassistant/components/growatt_server/sensor.py
|
homeassistant/components/growatt_server/sensor.py
|
||||||
@ -421,9 +420,6 @@ omit =
|
|||||||
homeassistant/components/harmony/data.py
|
homeassistant/components/harmony/data.py
|
||||||
homeassistant/components/harmony/remote.py
|
homeassistant/components/harmony/remote.py
|
||||||
homeassistant/components/harmony/util.py
|
homeassistant/components/harmony/util.py
|
||||||
homeassistant/components/hassio/binary_sensor.py
|
|
||||||
homeassistant/components/hassio/entity.py
|
|
||||||
homeassistant/components/hassio/sensor.py
|
|
||||||
homeassistant/components/haveibeenpwned/sensor.py
|
homeassistant/components/haveibeenpwned/sensor.py
|
||||||
homeassistant/components/hdmi_cec/*
|
homeassistant/components/hdmi_cec/*
|
||||||
homeassistant/components/heatmiser/climate.py
|
homeassistant/components/heatmiser/climate.py
|
||||||
@ -433,8 +429,9 @@ omit =
|
|||||||
homeassistant/components/hisense_aehw4a1/climate.py
|
homeassistant/components/hisense_aehw4a1/climate.py
|
||||||
homeassistant/components/hitron_coda/device_tracker.py
|
homeassistant/components/hitron_coda/device_tracker.py
|
||||||
homeassistant/components/hive/__init__.py
|
homeassistant/components/hive/__init__.py
|
||||||
homeassistant/components/hive/climate.py
|
homeassistant/components/hive/alarm_control_panel.py
|
||||||
homeassistant/components/hive/binary_sensor.py
|
homeassistant/components/hive/binary_sensor.py
|
||||||
|
homeassistant/components/hive/climate.py
|
||||||
homeassistant/components/hive/light.py
|
homeassistant/components/hive/light.py
|
||||||
homeassistant/components/hive/sensor.py
|
homeassistant/components/hive/sensor.py
|
||||||
homeassistant/components/hive/switch.py
|
homeassistant/components/hive/switch.py
|
||||||
@ -502,7 +499,6 @@ omit =
|
|||||||
homeassistant/components/incomfort/*
|
homeassistant/components/incomfort/*
|
||||||
homeassistant/components/intesishome/*
|
homeassistant/components/intesishome/*
|
||||||
homeassistant/components/ios/*
|
homeassistant/components/ios/*
|
||||||
homeassistant/components/iota/*
|
|
||||||
homeassistant/components/iperf3/*
|
homeassistant/components/iperf3/*
|
||||||
homeassistant/components/iqvia/*
|
homeassistant/components/iqvia/*
|
||||||
homeassistant/components/irish_rail_transport/sensor.py
|
homeassistant/components/irish_rail_transport/sensor.py
|
||||||
@ -521,6 +517,8 @@ omit =
|
|||||||
homeassistant/components/isy994/switch.py
|
homeassistant/components/isy994/switch.py
|
||||||
homeassistant/components/itach/remote.py
|
homeassistant/components/itach/remote.py
|
||||||
homeassistant/components/itunes/media_player.py
|
homeassistant/components/itunes/media_player.py
|
||||||
|
homeassistant/components/jellyfin/__init__.py
|
||||||
|
homeassistant/components/jellyfin/media_source.py
|
||||||
homeassistant/components/joaoapps_join/*
|
homeassistant/components/joaoapps_join/*
|
||||||
homeassistant/components/juicenet/__init__.py
|
homeassistant/components/juicenet/__init__.py
|
||||||
homeassistant/components/juicenet/const.py
|
homeassistant/components/juicenet/const.py
|
||||||
@ -541,7 +539,14 @@ omit =
|
|||||||
homeassistant/components/keyboard_remote/*
|
homeassistant/components/keyboard_remote/*
|
||||||
homeassistant/components/kira/*
|
homeassistant/components/kira/*
|
||||||
homeassistant/components/kiwi/lock.py
|
homeassistant/components/kiwi/lock.py
|
||||||
homeassistant/components/knx/*
|
homeassistant/components/knx/__init__.py
|
||||||
|
homeassistant/components/knx/climate.py
|
||||||
|
homeassistant/components/knx/cover.py
|
||||||
|
homeassistant/components/knx/expose.py
|
||||||
|
homeassistant/components/knx/knx_entity.py
|
||||||
|
homeassistant/components/knx/light.py
|
||||||
|
homeassistant/components/knx/notify.py
|
||||||
|
homeassistant/components/knx/schema.py
|
||||||
homeassistant/components/kodi/__init__.py
|
homeassistant/components/kodi/__init__.py
|
||||||
homeassistant/components/kodi/browse_media.py
|
homeassistant/components/kodi/browse_media.py
|
||||||
homeassistant/components/kodi/const.py
|
homeassistant/components/kodi/const.py
|
||||||
@ -551,7 +556,9 @@ omit =
|
|||||||
homeassistant/components/kostal_plenticore/__init__.py
|
homeassistant/components/kostal_plenticore/__init__.py
|
||||||
homeassistant/components/kostal_plenticore/const.py
|
homeassistant/components/kostal_plenticore/const.py
|
||||||
homeassistant/components/kostal_plenticore/helper.py
|
homeassistant/components/kostal_plenticore/helper.py
|
||||||
|
homeassistant/components/kostal_plenticore/select.py
|
||||||
homeassistant/components/kostal_plenticore/sensor.py
|
homeassistant/components/kostal_plenticore/sensor.py
|
||||||
|
homeassistant/components/kostal_plenticore/switch.py
|
||||||
homeassistant/components/kwb/sensor.py
|
homeassistant/components/kwb/sensor.py
|
||||||
homeassistant/components/lacrosse/sensor.py
|
homeassistant/components/lacrosse/sensor.py
|
||||||
homeassistant/components/lametric/*
|
homeassistant/components/lametric/*
|
||||||
@ -590,7 +597,6 @@ omit =
|
|||||||
homeassistant/components/lookin/models.py
|
homeassistant/components/lookin/models.py
|
||||||
homeassistant/components/lookin/sensor.py
|
homeassistant/components/lookin/sensor.py
|
||||||
homeassistant/components/lookin/climate.py
|
homeassistant/components/lookin/climate.py
|
||||||
homeassistant/components/loopenergy/sensor.py
|
|
||||||
homeassistant/components/luci/device_tracker.py
|
homeassistant/components/luci/device_tracker.py
|
||||||
homeassistant/components/luftdaten/__init__.py
|
homeassistant/components/luftdaten/__init__.py
|
||||||
homeassistant/components/luftdaten/sensor.py
|
homeassistant/components/luftdaten/sensor.py
|
||||||
@ -640,7 +646,6 @@ omit =
|
|||||||
homeassistant/components/miflora/sensor.py
|
homeassistant/components/miflora/sensor.py
|
||||||
homeassistant/components/mikrotik/hub.py
|
homeassistant/components/mikrotik/hub.py
|
||||||
homeassistant/components/mikrotik/device_tracker.py
|
homeassistant/components/mikrotik/device_tracker.py
|
||||||
homeassistant/components/mill/__init__.py
|
|
||||||
homeassistant/components/mill/climate.py
|
homeassistant/components/mill/climate.py
|
||||||
homeassistant/components/mill/const.py
|
homeassistant/components/mill/const.py
|
||||||
homeassistant/components/mill/sensor.py
|
homeassistant/components/mill/sensor.py
|
||||||
@ -669,7 +674,6 @@ omit =
|
|||||||
homeassistant/components/mutesync/binary_sensor.py
|
homeassistant/components/mutesync/binary_sensor.py
|
||||||
homeassistant/components/nest/const.py
|
homeassistant/components/nest/const.py
|
||||||
homeassistant/components/mvglive/sensor.py
|
homeassistant/components/mvglive/sensor.py
|
||||||
homeassistant/components/mychevy/*
|
|
||||||
homeassistant/components/mycroft/*
|
homeassistant/components/mycroft/*
|
||||||
homeassistant/components/mysensors/__init__.py
|
homeassistant/components/mysensors/__init__.py
|
||||||
homeassistant/components/mysensors/binary_sensor.py
|
homeassistant/components/mysensors/binary_sensor.py
|
||||||
@ -692,6 +696,8 @@ omit =
|
|||||||
homeassistant/components/myq/light.py
|
homeassistant/components/myq/light.py
|
||||||
homeassistant/components/nad/media_player.py
|
homeassistant/components/nad/media_player.py
|
||||||
homeassistant/components/nanoleaf/__init__.py
|
homeassistant/components/nanoleaf/__init__.py
|
||||||
|
homeassistant/components/nanoleaf/button.py
|
||||||
|
homeassistant/components/nanoleaf/entity.py
|
||||||
homeassistant/components/nanoleaf/light.py
|
homeassistant/components/nanoleaf/light.py
|
||||||
homeassistant/components/neato/__init__.py
|
homeassistant/components/neato/__init__.py
|
||||||
homeassistant/components/neato/api.py
|
homeassistant/components/neato/api.py
|
||||||
@ -871,6 +877,8 @@ omit =
|
|||||||
homeassistant/components/remote_rpi_gpio/*
|
homeassistant/components/remote_rpi_gpio/*
|
||||||
homeassistant/components/rest/notify.py
|
homeassistant/components/rest/notify.py
|
||||||
homeassistant/components/rest/switch.py
|
homeassistant/components/rest/switch.py
|
||||||
|
homeassistant/components/ridwell/__init__.py
|
||||||
|
homeassistant/components/ridwell/sensor.py
|
||||||
homeassistant/components/ring/camera.py
|
homeassistant/components/ring/camera.py
|
||||||
homeassistant/components/ripple/sensor.py
|
homeassistant/components/ripple/sensor.py
|
||||||
homeassistant/components/rocketchat/notify.py
|
homeassistant/components/rocketchat/notify.py
|
||||||
@ -906,6 +914,7 @@ omit =
|
|||||||
homeassistant/components/screenlogic/binary_sensor.py
|
homeassistant/components/screenlogic/binary_sensor.py
|
||||||
homeassistant/components/screenlogic/climate.py
|
homeassistant/components/screenlogic/climate.py
|
||||||
homeassistant/components/screenlogic/light.py
|
homeassistant/components/screenlogic/light.py
|
||||||
|
homeassistant/components/screenlogic/number.py
|
||||||
homeassistant/components/screenlogic/sensor.py
|
homeassistant/components/screenlogic/sensor.py
|
||||||
homeassistant/components/screenlogic/services.py
|
homeassistant/components/screenlogic/services.py
|
||||||
homeassistant/components/screenlogic/switch.py
|
homeassistant/components/screenlogic/switch.py
|
||||||
@ -926,6 +935,7 @@ omit =
|
|||||||
homeassistant/components/shodan/sensor.py
|
homeassistant/components/shodan/sensor.py
|
||||||
homeassistant/components/shelly/__init__.py
|
homeassistant/components/shelly/__init__.py
|
||||||
homeassistant/components/shelly/binary_sensor.py
|
homeassistant/components/shelly/binary_sensor.py
|
||||||
|
homeassistant/components/shelly/climate.py
|
||||||
homeassistant/components/shelly/entity.py
|
homeassistant/components/shelly/entity.py
|
||||||
homeassistant/components/shelly/light.py
|
homeassistant/components/shelly/light.py
|
||||||
homeassistant/components/shelly/sensor.py
|
homeassistant/components/shelly/sensor.py
|
||||||
@ -1081,6 +1091,14 @@ omit =
|
|||||||
homeassistant/components/todoist/calendar.py
|
homeassistant/components/todoist/calendar.py
|
||||||
homeassistant/components/todoist/const.py
|
homeassistant/components/todoist/const.py
|
||||||
homeassistant/components/tof/sensor.py
|
homeassistant/components/tof/sensor.py
|
||||||
|
homeassistant/components/tolo/__init__.py
|
||||||
|
homeassistant/components/tolo/binary_sensor.py
|
||||||
|
homeassistant/components/tolo/button.py
|
||||||
|
homeassistant/components/tolo/climate.py
|
||||||
|
homeassistant/components/tolo/fan.py
|
||||||
|
homeassistant/components/tolo/light.py
|
||||||
|
homeassistant/components/tolo/select.py
|
||||||
|
homeassistant/components/tolo/sensor.py
|
||||||
homeassistant/components/tomato/device_tracker.py
|
homeassistant/components/tomato/device_tracker.py
|
||||||
homeassistant/components/toon/__init__.py
|
homeassistant/components/toon/__init__.py
|
||||||
homeassistant/components/toon/binary_sensor.py
|
homeassistant/components/toon/binary_sensor.py
|
||||||
@ -1115,6 +1133,7 @@ omit =
|
|||||||
homeassistant/components/tradfri/sensor.py
|
homeassistant/components/tradfri/sensor.py
|
||||||
homeassistant/components/tradfri/switch.py
|
homeassistant/components/tradfri/switch.py
|
||||||
homeassistant/components/trafikverket_train/sensor.py
|
homeassistant/components/trafikverket_train/sensor.py
|
||||||
|
homeassistant/components/trafikverket_weatherstation/__init__.py
|
||||||
homeassistant/components/trafikverket_weatherstation/sensor.py
|
homeassistant/components/trafikverket_weatherstation/sensor.py
|
||||||
homeassistant/components/transmission/sensor.py
|
homeassistant/components/transmission/sensor.py
|
||||||
homeassistant/components/transmission/switch.py
|
homeassistant/components/transmission/switch.py
|
||||||
@ -1124,6 +1143,7 @@ omit =
|
|||||||
homeassistant/components/tuya/__init__.py
|
homeassistant/components/tuya/__init__.py
|
||||||
homeassistant/components/tuya/base.py
|
homeassistant/components/tuya/base.py
|
||||||
homeassistant/components/tuya/binary_sensor.py
|
homeassistant/components/tuya/binary_sensor.py
|
||||||
|
homeassistant/components/tuya/button.py
|
||||||
homeassistant/components/tuya/camera.py
|
homeassistant/components/tuya/camera.py
|
||||||
homeassistant/components/tuya/climate.py
|
homeassistant/components/tuya/climate.py
|
||||||
homeassistant/components/tuya/const.py
|
homeassistant/components/tuya/const.py
|
||||||
@ -1139,8 +1159,6 @@ omit =
|
|||||||
homeassistant/components/tuya/switch.py
|
homeassistant/components/tuya/switch.py
|
||||||
homeassistant/components/tuya/util.py
|
homeassistant/components/tuya/util.py
|
||||||
homeassistant/components/tuya/vacuum.py
|
homeassistant/components/tuya/vacuum.py
|
||||||
homeassistant/components/twentemilieu/const.py
|
|
||||||
homeassistant/components/twentemilieu/sensor.py
|
|
||||||
homeassistant/components/twilio_call/notify.py
|
homeassistant/components/twilio_call/notify.py
|
||||||
homeassistant/components/twilio_sms/notify.py
|
homeassistant/components/twilio_sms/notify.py
|
||||||
homeassistant/components/twitter/notify.py
|
homeassistant/components/twitter/notify.py
|
||||||
@ -1169,7 +1187,9 @@ omit =
|
|||||||
homeassistant/components/velbus/switch.py
|
homeassistant/components/velbus/switch.py
|
||||||
homeassistant/components/velux/*
|
homeassistant/components/velux/*
|
||||||
homeassistant/components/venstar/__init__.py
|
homeassistant/components/venstar/__init__.py
|
||||||
|
homeassistant/components/venstar/binary_sensor.py
|
||||||
homeassistant/components/venstar/climate.py
|
homeassistant/components/venstar/climate.py
|
||||||
|
homeassistant/components/venstar/sensor.py
|
||||||
homeassistant/components/verisure/__init__.py
|
homeassistant/components/verisure/__init__.py
|
||||||
homeassistant/components/verisure/alarm_control_panel.py
|
homeassistant/components/verisure/alarm_control_panel.py
|
||||||
homeassistant/components/verisure/binary_sensor.py
|
homeassistant/components/verisure/binary_sensor.py
|
||||||
@ -1186,7 +1206,12 @@ omit =
|
|||||||
homeassistant/components/vesync/light.py
|
homeassistant/components/vesync/light.py
|
||||||
homeassistant/components/vesync/switch.py
|
homeassistant/components/vesync/switch.py
|
||||||
homeassistant/components/viaggiatreno/sensor.py
|
homeassistant/components/viaggiatreno/sensor.py
|
||||||
homeassistant/components/vicare/*
|
homeassistant/components/vicare/binary_sensor.py
|
||||||
|
homeassistant/components/vicare/climate.py
|
||||||
|
homeassistant/components/vicare/const.py
|
||||||
|
homeassistant/components/vicare/__init__.py
|
||||||
|
homeassistant/components/vicare/sensor.py
|
||||||
|
homeassistant/components/vicare/water_heater.py
|
||||||
homeassistant/components/vilfo/__init__.py
|
homeassistant/components/vilfo/__init__.py
|
||||||
homeassistant/components/vilfo/sensor.py
|
homeassistant/components/vilfo/sensor.py
|
||||||
homeassistant/components/vilfo/const.py
|
homeassistant/components/vilfo/const.py
|
||||||
@ -1263,6 +1288,7 @@ omit =
|
|||||||
homeassistant/components/yale_smart_alarm/coordinator.py
|
homeassistant/components/yale_smart_alarm/coordinator.py
|
||||||
homeassistant/components/yamaha_musiccast/__init__.py
|
homeassistant/components/yamaha_musiccast/__init__.py
|
||||||
homeassistant/components/yamaha_musiccast/media_player.py
|
homeassistant/components/yamaha_musiccast/media_player.py
|
||||||
|
homeassistant/components/yamaha_musiccast/number.py
|
||||||
homeassistant/components/yandex_transport/*
|
homeassistant/components/yandex_transport/*
|
||||||
homeassistant/components/yeelightsunflower/light.py
|
homeassistant/components/yeelightsunflower/light.py
|
||||||
homeassistant/components/yi/camera.py
|
homeassistant/components/yi/camera.py
|
||||||
|
41
.github/workflows/builder.yml
vendored
41
.github/workflows/builder.yml
vendored
@ -23,12 +23,12 @@ jobs:
|
|||||||
publish: ${{ steps.version.outputs.publish }}
|
publish: ${{ steps.version.outputs.publish }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v2.3.1
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
|
|
||||||
@ -56,9 +56,7 @@ jobs:
|
|||||||
uses: home-assistant/actions/helpers/codenotary@master
|
uses: home-assistant/actions/helpers/codenotary@master
|
||||||
with:
|
with:
|
||||||
source: file://${{ github.workspace }}/OFFICIAL_IMAGE
|
source: file://${{ github.workspace }}/OFFICIAL_IMAGE
|
||||||
user: ${{ secrets.VCN_USER }}
|
token: ${{ secrets.CAS_TOKEN }}
|
||||||
password: ${{ secrets.VCN_PASSWORD }}
|
|
||||||
organisation: home-assistant.io
|
|
||||||
|
|
||||||
build_python:
|
build_python:
|
||||||
name: Build PyPi package
|
name: Build PyPi package
|
||||||
@ -67,10 +65,10 @@ jobs:
|
|||||||
if: needs.init.outputs.publish == 'true'
|
if: needs.init.outputs.publish == 'true'
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v2.3.1
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
|
|
||||||
@ -97,11 +95,11 @@ jobs:
|
|||||||
arch: ${{ fromJson(needs.init.outputs.architectures) }}
|
arch: ${{ fromJson(needs.init.outputs.architectures) }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
if: needs.init.outputs.channel == 'dev'
|
if: needs.init.outputs.channel == 'dev'
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v2.3.1
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
|
|
||||||
@ -133,15 +131,15 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build base image
|
- name: Build base image
|
||||||
uses: home-assistant/builder@2021.09.0
|
uses: home-assistant/builder@2021.11.4
|
||||||
with:
|
with:
|
||||||
args: |
|
args: |
|
||||||
$BUILD_ARGS \
|
$BUILD_ARGS \
|
||||||
--${{ matrix.arch }} \
|
--${{ matrix.arch }} \
|
||||||
--target /data \
|
--target /data \
|
||||||
--with-codenotary "${{ secrets.VCN_USER }}" "${{ secrets.VCN_PASSWORD }}" "${{ secrets.VCN_ORG }}" \
|
|
||||||
--validate-from "${{ secrets.VCN_ORG }}" \
|
|
||||||
--generic ${{ needs.init.outputs.version }}
|
--generic ${{ needs.init.outputs.version }}
|
||||||
|
env:
|
||||||
|
CAS_API_KEY: ${{ secrets.CAS_TOKEN }}
|
||||||
|
|
||||||
build_machine:
|
build_machine:
|
||||||
name: Build ${{ matrix.machine }} machine core image
|
name: Build ${{ matrix.machine }} machine core image
|
||||||
@ -170,7 +168,7 @@ jobs:
|
|||||||
- tinker
|
- tinker
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
uses: docker/login-action@v1.10.0
|
uses: docker/login-action@v1.10.0
|
||||||
@ -186,14 +184,14 @@ jobs:
|
|||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Build base image
|
- name: Build base image
|
||||||
uses: home-assistant/builder@2021.09.0
|
uses: home-assistant/builder@2021.11.4
|
||||||
with:
|
with:
|
||||||
args: |
|
args: |
|
||||||
$BUILD_ARGS \
|
$BUILD_ARGS \
|
||||||
--target /data/machine \
|
--target /data/machine \
|
||||||
--with-codenotary "${{ secrets.VCN_USER }}" "${{ secrets.VCN_PASSWORD }}" "${{ secrets.VCN_ORG }}" \
|
|
||||||
--validate-from "${{ secrets.VCN_ORG }}" \
|
|
||||||
--machine "${{ needs.init.outputs.version }}=${{ matrix.machine }}"
|
--machine "${{ needs.init.outputs.version }}=${{ matrix.machine }}"
|
||||||
|
env:
|
||||||
|
CAS_API_KEY: ${{ secrets.CAS_TOKEN }}
|
||||||
|
|
||||||
publish_ha:
|
publish_ha:
|
||||||
name: Publish version files
|
name: Publish version files
|
||||||
@ -201,7 +199,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
- name: Initialize git
|
- name: Initialize git
|
||||||
uses: home-assistant/actions/helpers/git-init@master
|
uses: home-assistant/actions/helpers/git-init@master
|
||||||
@ -233,7 +231,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
- name: Login to DockerHub
|
- name: Login to DockerHub
|
||||||
uses: docker/login-action@v1.10.0
|
uses: docker/login-action@v1.10.0
|
||||||
@ -248,8 +246,8 @@ jobs:
|
|||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
password: ${{ secrets.GITHUB_TOKEN }}
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Install VCN tools
|
- name: Install CAS tools
|
||||||
uses: home-assistant/actions/helpers/vcn@master
|
uses: home-assistant/actions/helpers/cas@master
|
||||||
|
|
||||||
- name: Build Meta Image
|
- name: Build Meta Image
|
||||||
shell: bash
|
shell: bash
|
||||||
@ -293,8 +291,7 @@ jobs:
|
|||||||
|
|
||||||
function validate_image() {
|
function validate_image() {
|
||||||
local image=${1}
|
local image=${1}
|
||||||
state="$(vcn authenticate --org home-assistant.io --output json docker://${image} | jq '.verification.status // 2')"
|
if ! cas authenticate --signerID notary@home-assistant.io "docker://${image}"; then
|
||||||
if [[ "${state}" != "0" ]]; then
|
|
||||||
echo "Invalid signature!"
|
echo "Invalid signature!"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
614
.github/workflows/ci.yaml
vendored
614
.github/workflows/ci.yaml
vendored
@ -15,7 +15,115 @@ env:
|
|||||||
PRE_COMMIT_CACHE: ~/.cache/pre-commit
|
PRE_COMMIT_CACHE: ~/.cache/pre-commit
|
||||||
SQLALCHEMY_WARN_20: 1
|
SQLALCHEMY_WARN_20: 1
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
changes:
|
||||||
|
name: Determine what has changed
|
||||||
|
outputs:
|
||||||
|
# In case of issues with the partial run, use the following line instead:
|
||||||
|
# test_full_suite: 'true'
|
||||||
|
test_full_suite: ${{ steps.info.outputs.test_full_suite }}
|
||||||
|
core: ${{ steps.core.outputs.changes }}
|
||||||
|
integrations: ${{ steps.integrations.outputs.changes }}
|
||||||
|
integrations_glob: ${{ steps.info.outputs.integrations_glob }}
|
||||||
|
tests: ${{ steps.info.outputs.tests }}
|
||||||
|
tests_glob: ${{ steps.info.outputs.tests_glob }}
|
||||||
|
test_groups: ${{ steps.info.outputs.test_groups }}
|
||||||
|
test_group_count: ${{ steps.info.outputs.test_group_count }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Check out code from GitHub
|
||||||
|
uses: actions/checkout@v2.4.0
|
||||||
|
- name: Filter for core changes
|
||||||
|
uses: dorny/paths-filter@v2.10.2
|
||||||
|
id: core
|
||||||
|
with:
|
||||||
|
filters: .core_files.yaml
|
||||||
|
- name: Create a list of integrations to filter for changes
|
||||||
|
run: |
|
||||||
|
integrations=$(ls -Ad ./homeassistant/components/[!_]* | xargs -n 1 basename)
|
||||||
|
touch .integration_paths.yaml
|
||||||
|
for integration in $integrations; do
|
||||||
|
echo "${integration}: [homeassistant/components/${integration}/*, tests/components/${integration}/*]" \
|
||||||
|
>> .integration_paths.yaml;
|
||||||
|
done
|
||||||
|
echo "Result:"
|
||||||
|
cat .integration_paths.yaml
|
||||||
|
- name: Filter for integration changes
|
||||||
|
uses: dorny/paths-filter@v2.10.2
|
||||||
|
id: integrations
|
||||||
|
with:
|
||||||
|
filters: .integration_paths.yaml
|
||||||
|
- name: Collect additional information
|
||||||
|
id: info
|
||||||
|
run: |
|
||||||
|
# Defaults
|
||||||
|
integrations_glob=""
|
||||||
|
test_full_suite="true"
|
||||||
|
test_groups="[1, 2, 3, 4, 5, 6]"
|
||||||
|
test_group_count=6
|
||||||
|
tests="[]"
|
||||||
|
tests_glob=""
|
||||||
|
|
||||||
|
if [[ "${{ steps.integrations.outputs.changes }}" != "[]" ]];
|
||||||
|
then
|
||||||
|
# Create a file glob for the integrations
|
||||||
|
integrations_glob=$(echo '${{ steps.integrations.outputs.changes }}' | jq -cSr '. | join(",")')
|
||||||
|
[[ "${integrations_glob}" == *","* ]] && integrations_glob="{${integrations_glob}}"
|
||||||
|
|
||||||
|
# Create list of testable integrations
|
||||||
|
possible_integrations=$(echo '${{ steps.integrations.outputs.changes }}' | jq -cSr '.[]')
|
||||||
|
tests=$(
|
||||||
|
for integration in ${possible_integrations};
|
||||||
|
do
|
||||||
|
if [[ -d "tests/components/${integration}" ]]; then
|
||||||
|
echo -n "\"${integration}\",";
|
||||||
|
fi;
|
||||||
|
done
|
||||||
|
)
|
||||||
|
|
||||||
|
[[ ! -z "${tests}" ]] && tests="${tests::-1}"
|
||||||
|
tests="[${tests}]"
|
||||||
|
test_groups="${tests}"
|
||||||
|
# Test group count should be 1, we don't split partial tests
|
||||||
|
test_group_count=1
|
||||||
|
|
||||||
|
# Create a file glob for the integrations tests
|
||||||
|
tests_glob=$(echo "${tests}" | jq -cSr '. | join(",")')
|
||||||
|
[[ "${tests_glob}" == *","* ]] && tests_glob="{${tests_glob}}"
|
||||||
|
|
||||||
|
test_full_suite="false"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# We need to run the full suite on certain branches.
|
||||||
|
# Or, in case core files are touched, for the full suite as well.
|
||||||
|
if [[ "${{ github.ref }}" == "refs/heads/dev" ]] \
|
||||||
|
|| [[ "${{ github.ref }}" == "refs/heads/master" ]] \
|
||||||
|
|| [[ "${{ github.ref }}" == "refs/heads/rc" ]] \
|
||||||
|
|| [[ "${{ steps.core.outputs.any }}" == "true" ]];
|
||||||
|
then
|
||||||
|
test_groups="[1, 2, 3, 4, 5, 6]"
|
||||||
|
test_group_count=6
|
||||||
|
test_full_suite="true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Output & sent to GitHub Actions
|
||||||
|
echo "test_full_suite: ${test_full_suite}"
|
||||||
|
echo "::set-output name=test_full_suite::${test_full_suite}"
|
||||||
|
echo "integrations_glob: ${integrations_glob}"
|
||||||
|
echo "::set-output name=integrations_glob::${integrations_glob}"
|
||||||
|
echo "test_group_count: ${test_group_count}"
|
||||||
|
echo "::set-output name=test_group_count::${test_group_count}"
|
||||||
|
echo "test_groups: ${test_groups}"
|
||||||
|
echo "::set-output name=test_groups::${test_groups}"
|
||||||
|
echo "tests: ${tests}"
|
||||||
|
echo "::set-output name=tests::${tests}"
|
||||||
|
echo "tests_glob: ${tests_glob}"
|
||||||
|
echo "::set-output name=tests_glob::${tests_glob}"
|
||||||
|
|
||||||
# Separate job to pre-populate the base dependency cache
|
# Separate job to pre-populate the base dependency cache
|
||||||
# This prevent upcoming jobs to do the same individually
|
# This prevent upcoming jobs to do the same individually
|
||||||
prepare-base:
|
prepare-base:
|
||||||
@ -26,10 +134,10 @@ jobs:
|
|||||||
pre-commit-key: ${{ steps.generate-pre-commit-key.outputs.key }}
|
pre-commit-key: ${{ steps.generate-pre-commit-key.outputs.key }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
id: python
|
id: python
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v2.3.1
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
- name: Generate partial Python venv restore key
|
- name: Generate partial Python venv restore key
|
||||||
@ -41,7 +149,7 @@ jobs:
|
|||||||
hashFiles('homeassistant/package_constraints.txt') }}"
|
hashFiles('homeassistant/package_constraints.txt') }}"
|
||||||
- name: Restore base Python virtual environment
|
- name: Restore base Python virtual environment
|
||||||
id: cache-venv
|
id: cache-venv
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: venv
|
path: venv
|
||||||
key: >-
|
key: >-
|
||||||
@ -65,7 +173,7 @@ jobs:
|
|||||||
hashFiles('.pre-commit-config.yaml') }}"
|
hashFiles('.pre-commit-config.yaml') }}"
|
||||||
- name: Restore pre-commit environment from cache
|
- name: Restore pre-commit environment from cache
|
||||||
id: cache-precommit
|
id: cache-precommit
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||||
key: >-
|
key: >-
|
||||||
@ -78,61 +186,23 @@ jobs:
|
|||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pre-commit install-hooks
|
pre-commit install-hooks
|
||||||
|
|
||||||
lint-bandit:
|
|
||||||
name: Check bandit
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: prepare-base
|
|
||||||
steps:
|
|
||||||
- name: Check out code from GitHub
|
|
||||||
uses: actions/checkout@v2.3.5
|
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
||||||
uses: actions/setup-python@v2.2.2
|
|
||||||
id: python
|
|
||||||
with:
|
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
||||||
- name: Restore base Python virtual environment
|
|
||||||
id: cache-venv
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: venv
|
|
||||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
|
||||||
needs.prepare-base.outputs.python-key }}
|
|
||||||
- name: Fail job if Python cache restore failed
|
|
||||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
echo "Failed to restore Python virtual environment from cache"
|
|
||||||
exit 1
|
|
||||||
- name: Restore pre-commit environment from cache
|
|
||||||
id: cache-precommit
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
|
||||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
|
||||||
- name: Fail job if pre-commit cache restore failed
|
|
||||||
if: steps.cache-precommit.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
echo "Failed to restore pre-commit environment from cache"
|
|
||||||
exit 1
|
|
||||||
- name: Run bandit
|
|
||||||
run: |
|
|
||||||
. venv/bin/activate
|
|
||||||
pre-commit run --hook-stage manual bandit --all-files --show-diff-on-failure
|
|
||||||
|
|
||||||
lint-black:
|
lint-black:
|
||||||
name: Check black
|
name: Check black
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: prepare-base
|
needs:
|
||||||
|
- changes
|
||||||
|
- prepare-base
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v2.3.1
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
- name: Restore base Python virtual environment
|
- name: Restore base Python virtual environment
|
||||||
id: cache-venv
|
id: cache-venv
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: venv
|
path: venv
|
||||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||||
@ -144,7 +214,7 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
- name: Restore pre-commit environment from cache
|
- name: Restore pre-commit environment from cache
|
||||||
id: cache-precommit
|
id: cache-precommit
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
||||||
@ -153,131 +223,35 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "Failed to restore pre-commit environment from cache"
|
echo "Failed to restore pre-commit environment from cache"
|
||||||
exit 1
|
exit 1
|
||||||
- name: Run black
|
- name: Run black (fully)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'true'
|
||||||
run: |
|
run: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pre-commit run --hook-stage manual black --all-files --show-diff-on-failure
|
pre-commit run --hook-stage manual black --all-files --show-diff-on-failure
|
||||||
|
- name: Run black (partially)
|
||||||
lint-codespell:
|
if: needs.changes.outputs.test_full_suite == 'false'
|
||||||
name: Check codespell
|
shell: bash
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: prepare-base
|
|
||||||
steps:
|
|
||||||
- name: Check out code from GitHub
|
|
||||||
uses: actions/checkout@v2.3.5
|
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
||||||
uses: actions/setup-python@v2.2.2
|
|
||||||
id: python
|
|
||||||
with:
|
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
||||||
- name: Restore base Python virtual environment
|
|
||||||
id: cache-venv
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: venv
|
|
||||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
|
||||||
needs.prepare-base.outputs.python-key }}
|
|
||||||
- name: Fail job if Python cache restore failed
|
|
||||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
echo "Failed to restore Python virtual environment from cache"
|
|
||||||
exit 1
|
|
||||||
- name: Restore pre-commit environment from cache
|
|
||||||
id: cache-precommit
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
|
||||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
|
||||||
- name: Fail job if pre-commit cache restore failed
|
|
||||||
if: steps.cache-precommit.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
echo "Failed to restore pre-commit environment from cache"
|
|
||||||
exit 1
|
|
||||||
- name: Register codespell problem matcher
|
|
||||||
run: |
|
|
||||||
echo "::add-matcher::.github/workflows/matchers/codespell.json"
|
|
||||||
- name: Run codespell
|
|
||||||
run: |
|
run: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pre-commit run --show-diff-on-failure --hook-stage manual codespell --all-files
|
pre-commit run --hook-stage manual black --files {homeassistant,tests}/components/${{ needs.changes.outputs.integrations_glob }}/* --show-diff-on-failure
|
||||||
|
|
||||||
lint-dockerfile:
|
|
||||||
name: Check Dockerfile
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: prepare-base
|
|
||||||
steps:
|
|
||||||
- name: Check out code from GitHub
|
|
||||||
uses: actions/checkout@v2.3.5
|
|
||||||
- name: Register hadolint problem matcher
|
|
||||||
run: |
|
|
||||||
echo "::add-matcher::.github/workflows/matchers/hadolint.json"
|
|
||||||
- name: Check Dockerfile
|
|
||||||
uses: docker://hadolint/hadolint:v1.18.2
|
|
||||||
with:
|
|
||||||
args: hadolint Dockerfile
|
|
||||||
- name: Check Dockerfile.dev
|
|
||||||
uses: docker://hadolint/hadolint:v1.18.2
|
|
||||||
with:
|
|
||||||
args: hadolint Dockerfile.dev
|
|
||||||
|
|
||||||
lint-executable-shebangs:
|
|
||||||
name: Check executables
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: prepare-base
|
|
||||||
steps:
|
|
||||||
- name: Check out code from GitHub
|
|
||||||
uses: actions/checkout@v2.3.5
|
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
||||||
uses: actions/setup-python@v2.2.2
|
|
||||||
id: python
|
|
||||||
with:
|
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
||||||
- name: Restore base Python virtual environment
|
|
||||||
id: cache-venv
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: venv
|
|
||||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
|
||||||
needs.prepare-base.outputs.python-key }}
|
|
||||||
- name: Fail job if Python cache restore failed
|
|
||||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
echo "Failed to restore Python virtual environment from cache"
|
|
||||||
exit 1
|
|
||||||
- name: Restore pre-commit environment from cache
|
|
||||||
id: cache-precommit
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
|
||||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
|
||||||
- name: Fail job if pre-commit cache restore failed
|
|
||||||
if: steps.cache-precommit.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
echo "Failed to restore pre-commit environment from cache"
|
|
||||||
exit 1
|
|
||||||
- name: Register check executables problem matcher
|
|
||||||
run: |
|
|
||||||
echo "::add-matcher::.github/workflows/matchers/check-executables-have-shebangs.json"
|
|
||||||
- name: Run executables check
|
|
||||||
run: |
|
|
||||||
. venv/bin/activate
|
|
||||||
pre-commit run --hook-stage manual check-executables-have-shebangs --all-files
|
|
||||||
|
|
||||||
lint-flake8:
|
lint-flake8:
|
||||||
name: Check flake8
|
name: Check flake8
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: prepare-base
|
needs:
|
||||||
|
- changes
|
||||||
|
- prepare-base
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v2.3.1
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
- name: Restore base Python virtual environment
|
- name: Restore base Python virtual environment
|
||||||
id: cache-venv
|
id: cache-venv
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: venv
|
path: venv
|
||||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||||
@ -289,7 +263,7 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
- name: Restore pre-commit environment from cache
|
- name: Restore pre-commit environment from cache
|
||||||
id: cache-precommit
|
id: cache-precommit
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
||||||
@ -301,10 +275,17 @@ jobs:
|
|||||||
- name: Register flake8 problem matcher
|
- name: Register flake8 problem matcher
|
||||||
run: |
|
run: |
|
||||||
echo "::add-matcher::.github/workflows/matchers/flake8.json"
|
echo "::add-matcher::.github/workflows/matchers/flake8.json"
|
||||||
- name: Run flake8
|
- name: Run flake8 (fully)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'true'
|
||||||
run: |
|
run: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pre-commit run --hook-stage manual flake8 --all-files
|
pre-commit run --hook-stage manual flake8 --all-files
|
||||||
|
- name: Run flake8 (partially)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'false'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
. venv/bin/activate
|
||||||
|
pre-commit run --hook-stage manual flake8 --files {homeassistant,tests}/components/${{ needs.changes.outputs.integrations_glob }}/*
|
||||||
|
|
||||||
lint-isort:
|
lint-isort:
|
||||||
name: Check isort
|
name: Check isort
|
||||||
@ -312,15 +293,15 @@ jobs:
|
|||||||
needs: prepare-base
|
needs: prepare-base
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v2.3.1
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
- name: Restore base Python virtual environment
|
- name: Restore base Python virtual environment
|
||||||
id: cache-venv
|
id: cache-venv
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: venv
|
path: venv
|
||||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||||
@ -332,7 +313,7 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
- name: Restore pre-commit environment from cache
|
- name: Restore pre-commit environment from cache
|
||||||
id: cache-precommit
|
id: cache-precommit
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
||||||
@ -346,21 +327,23 @@ jobs:
|
|||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pre-commit run --hook-stage manual isort --all-files --show-diff-on-failure
|
pre-commit run --hook-stage manual isort --all-files --show-diff-on-failure
|
||||||
|
|
||||||
lint-json:
|
lint-other:
|
||||||
name: Check JSON
|
name: Check other linters
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: prepare-base
|
needs:
|
||||||
|
- changes
|
||||||
|
- prepare-base
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v2.3.1
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
- name: Restore base Python virtual environment
|
- name: Restore base Python virtual environment
|
||||||
id: cache-venv
|
id: cache-venv
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: venv
|
path: venv
|
||||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||||
@ -372,7 +355,7 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
- name: Restore pre-commit environment from cache
|
- name: Restore pre-commit environment from cache
|
||||||
id: cache-precommit
|
id: cache-precommit
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
path: ${{ env.PRE_COMMIT_CACHE }}
|
||||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
||||||
@ -381,6 +364,27 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "Failed to restore pre-commit environment from cache"
|
echo "Failed to restore pre-commit environment from cache"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
||||||
|
- name: Run pyupgrade (fully)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'true'
|
||||||
|
run: |
|
||||||
|
. venv/bin/activate
|
||||||
|
pre-commit run --hook-stage manual pyupgrade --all-files --show-diff-on-failure
|
||||||
|
- name: Run pyupgrade (partially)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'false'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
. venv/bin/activate
|
||||||
|
pre-commit run --hook-stage manual pyupgrade --files {homeassistant,tests}/components/${{ needs.changes.outputs.integrations_glob }}/* --show-diff-on-failure
|
||||||
|
|
||||||
|
- name: Register yamllint problem matcher
|
||||||
|
run: |
|
||||||
|
echo "::add-matcher::.github/workflows/matchers/yamllint.json"
|
||||||
|
- name: Run yamllint
|
||||||
|
run: |
|
||||||
|
. venv/bin/activate
|
||||||
|
pre-commit run --hook-stage manual yamllint --all-files --show-diff-on-failure
|
||||||
|
|
||||||
- name: Register check-json problem matcher
|
- name: Register check-json problem matcher
|
||||||
run: |
|
run: |
|
||||||
echo "::add-matcher::.github/workflows/matchers/check-json.json"
|
echo "::add-matcher::.github/workflows/matchers/check-json.json"
|
||||||
@ -389,99 +393,45 @@ jobs:
|
|||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pre-commit run --hook-stage manual check-json --all-files
|
pre-commit run --hook-stage manual check-json --all-files
|
||||||
|
|
||||||
lint-pyupgrade:
|
- name: Register check executables problem matcher
|
||||||
name: Check pyupgrade
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: prepare-base
|
|
||||||
steps:
|
|
||||||
- name: Check out code from GitHub
|
|
||||||
uses: actions/checkout@v2.3.5
|
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
||||||
uses: actions/setup-python@v2.2.2
|
|
||||||
id: python
|
|
||||||
with:
|
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
||||||
- name: Restore base Python virtual environment
|
|
||||||
id: cache-venv
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: venv
|
|
||||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
|
||||||
needs.prepare-base.outputs.python-key }}
|
|
||||||
- name: Fail job if Python cache restore failed
|
|
||||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
run: |
|
||||||
echo "Failed to restore Python virtual environment from cache"
|
echo "::add-matcher::.github/workflows/matchers/check-executables-have-shebangs.json"
|
||||||
exit 1
|
- name: Run executables check
|
||||||
- name: Restore pre-commit environment from cache
|
|
||||||
id: cache-precommit
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
|
||||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
|
||||||
- name: Fail job if pre-commit cache restore failed
|
|
||||||
if: steps.cache-precommit.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
echo "Failed to restore pre-commit environment from cache"
|
|
||||||
exit 1
|
|
||||||
- name: Run pyupgrade
|
|
||||||
run: |
|
run: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pre-commit run --hook-stage manual pyupgrade --all-files --show-diff-on-failure
|
pre-commit run --hook-stage manual check-executables-have-shebangs --all-files
|
||||||
|
|
||||||
# Disabled until we have the existing issues fixed
|
- name: Register codespell problem matcher
|
||||||
# lint-shellcheck:
|
|
||||||
# name: Check ShellCheck
|
|
||||||
# runs-on: ubuntu-latest
|
|
||||||
# needs: prepare-base
|
|
||||||
# steps:
|
|
||||||
# - name: Check out code from GitHub
|
|
||||||
# uses: actions/checkout@v2.3.5
|
|
||||||
# - name: Run ShellCheck
|
|
||||||
# uses: ludeeus/action-shellcheck@0.3.0
|
|
||||||
|
|
||||||
lint-yaml:
|
|
||||||
name: Check YAML
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: prepare-base
|
|
||||||
steps:
|
|
||||||
- name: Check out code from GitHub
|
|
||||||
uses: actions/checkout@v2.3.5
|
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
|
||||||
uses: actions/setup-python@v2.2.2
|
|
||||||
id: python
|
|
||||||
with:
|
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
|
||||||
- name: Restore base Python virtual environment
|
|
||||||
id: cache-venv
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: venv
|
|
||||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
|
||||||
needs.prepare-base.outputs.python-key }}
|
|
||||||
- name: Fail job if Python cache restore failed
|
|
||||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
run: |
|
||||||
echo "Failed to restore Python virtual environment from cache"
|
echo "::add-matcher::.github/workflows/matchers/codespell.json"
|
||||||
exit 1
|
- name: Run codespell
|
||||||
- name: Restore pre-commit environment from cache
|
|
||||||
id: cache-precommit
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: ${{ env.PRE_COMMIT_CACHE }}
|
|
||||||
key: ${{ runner.os }}-${{ needs.prepare-base.outputs.pre-commit-key }}
|
|
||||||
- name: Fail job if pre-commit cache restore failed
|
|
||||||
if: steps.cache-precommit.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
echo "Failed to restore pre-commit environment from cache"
|
|
||||||
exit 1
|
|
||||||
- name: Register yamllint problem matcher
|
|
||||||
run: |
|
|
||||||
echo "::add-matcher::.github/workflows/matchers/yamllint.json"
|
|
||||||
- name: Run yamllint
|
|
||||||
run: |
|
run: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pre-commit run --hook-stage manual yamllint --all-files --show-diff-on-failure
|
pre-commit run --show-diff-on-failure --hook-stage manual codespell --all-files
|
||||||
|
|
||||||
|
- name: Register hadolint problem matcher
|
||||||
|
run: |
|
||||||
|
echo "::add-matcher::.github/workflows/matchers/hadolint.json"
|
||||||
|
- name: Check Dockerfile
|
||||||
|
uses: docker://hadolint/hadolint:v1.18.2
|
||||||
|
with:
|
||||||
|
args: hadolint Dockerfile
|
||||||
|
- name: Check Dockerfile.dev
|
||||||
|
uses: docker://hadolint/hadolint:v1.18.2
|
||||||
|
with:
|
||||||
|
args: hadolint Dockerfile.dev
|
||||||
|
|
||||||
|
- name: Run bandit (fully)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'true'
|
||||||
|
run: |
|
||||||
|
. venv/bin/activate
|
||||||
|
pre-commit run --hook-stage manual bandit --all-files --show-diff-on-failure
|
||||||
|
- name: Run bandit (partially)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'false'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
. venv/bin/activate
|
||||||
|
pre-commit run --hook-stage manual bandit --files {homeassistant,tests}/components/${{ needs.changes.outputs.integrations_glob }}/* --show-diff-on-failure
|
||||||
|
|
||||||
hassfest:
|
hassfest:
|
||||||
name: Check hassfest
|
name: Check hassfest
|
||||||
@ -493,10 +443,10 @@ jobs:
|
|||||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||||
id: cache-venv
|
id: cache-venv
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: venv
|
path: venv
|
||||||
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||||
@ -517,15 +467,15 @@ jobs:
|
|||||||
needs: prepare-base
|
needs: prepare-base
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v2.3.1
|
||||||
id: python
|
id: python
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
- name: Restore base Python virtual environment
|
- name: Restore base Python virtual environment
|
||||||
id: cache-venv
|
id: cache-venv
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: venv
|
path: venv
|
||||||
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
key: ${{ runner.os }}-${{ steps.python.outputs.python-version }}-${{
|
||||||
@ -551,7 +501,7 @@ jobs:
|
|||||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
- name: Generate partial Python venv restore key
|
- name: Generate partial Python venv restore key
|
||||||
id: generate-python-key
|
id: generate-python-key
|
||||||
run: >-
|
run: >-
|
||||||
@ -561,7 +511,7 @@ jobs:
|
|||||||
hashFiles('homeassistant/package_constraints.txt') }}"
|
hashFiles('homeassistant/package_constraints.txt') }}"
|
||||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||||
id: cache-venv
|
id: cache-venv
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: venv
|
path: venv
|
||||||
key: >-
|
key: >-
|
||||||
@ -588,17 +538,19 @@ jobs:
|
|||||||
pylint:
|
pylint:
|
||||||
name: Check pylint
|
name: Check pylint
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: prepare-tests
|
needs:
|
||||||
|
- changes
|
||||||
|
- prepare-tests
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [3.8]
|
python-version: [3.8]
|
||||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||||
id: cache-venv
|
id: cache-venv
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: venv
|
path: venv
|
||||||
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||||
@ -611,25 +563,34 @@ jobs:
|
|||||||
- name: Register pylint problem matcher
|
- name: Register pylint problem matcher
|
||||||
run: |
|
run: |
|
||||||
echo "::add-matcher::.github/workflows/matchers/pylint.json"
|
echo "::add-matcher::.github/workflows/matchers/pylint.json"
|
||||||
- name: Run pylint
|
- name: Run pylint (fully)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'true'
|
||||||
run: |
|
run: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
pylint homeassistant
|
pylint homeassistant
|
||||||
|
- name: Run pylint (partially)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'false'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
. venv/bin/activate
|
||||||
|
pylint homeassistant/components/${{ needs.changes.outputs.integrations_glob }}
|
||||||
|
|
||||||
mypy:
|
mypy:
|
||||||
name: Check mypy
|
name: Check mypy
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: prepare-tests
|
needs:
|
||||||
|
- changes
|
||||||
|
- prepare-tests
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
python-version: [3.8]
|
python-version: [3.8]
|
||||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||||
id: cache-venv
|
id: cache-venv
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: venv
|
path: venv
|
||||||
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||||
@ -642,28 +603,44 @@ jobs:
|
|||||||
- name: Register mypy problem matcher
|
- name: Register mypy problem matcher
|
||||||
run: |
|
run: |
|
||||||
echo "::add-matcher::.github/workflows/matchers/mypy.json"
|
echo "::add-matcher::.github/workflows/matchers/mypy.json"
|
||||||
- name: Run mypy
|
- name: Run mypy (fully)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'true'
|
||||||
run: |
|
run: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
mypy homeassistant
|
mypy homeassistant
|
||||||
|
- name: Run mypy (partially)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'false'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
. venv/bin/activate
|
||||||
|
mypy homeassistant/components/${{ needs.changes.outputs.integrations_glob }}
|
||||||
|
|
||||||
pytest:
|
pytest:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: prepare-tests
|
if: needs.changes.outputs.test_full_suite == 'true' || needs.changes.outputs.tests_glob
|
||||||
|
needs:
|
||||||
|
- changes
|
||||||
|
- gen-requirements-all
|
||||||
|
- hassfest
|
||||||
|
- lint-black
|
||||||
|
- lint-other
|
||||||
|
- lint-isort
|
||||||
|
- mypy
|
||||||
|
- prepare-tests
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
group: [1, 2, 3, 4]
|
group: ${{ fromJson(needs.changes.outputs.test_groups) }}
|
||||||
python-version: [3.8, 3.9]
|
python-version: [3.8, 3.9]
|
||||||
name: >-
|
name: >-
|
||||||
Run tests Python ${{ matrix.python-version }} (group ${{ matrix.group }})
|
Run tests Python ${{ matrix.python-version }} (${{ matrix.group }})
|
||||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
||||||
id: cache-venv
|
id: cache-venv
|
||||||
uses: actions/cache@v2.1.6
|
uses: actions/cache@v2.1.7
|
||||||
with:
|
with:
|
||||||
path: venv
|
path: venv
|
||||||
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
||||||
@ -683,61 +660,82 @@ jobs:
|
|||||||
# However this plugin is fairly new and doesn't run correctly
|
# However this plugin is fairly new and doesn't run correctly
|
||||||
# on a non-GitHub environment.
|
# on a non-GitHub environment.
|
||||||
pip install pytest-github-actions-annotate-failures==0.1.3
|
pip install pytest-github-actions-annotate-failures==0.1.3
|
||||||
- name: Run pytest
|
- name: Register pytest slow test problem matcher
|
||||||
|
run: |
|
||||||
|
echo "::add-matcher::.github/workflows/matchers/pytest-slow.json"
|
||||||
|
- name: Run pytest (fully)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'true'
|
||||||
run: |
|
run: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
python3 -X dev -bb -m pytest \
|
python3 -X dev -m pytest \
|
||||||
-qq \
|
-qq \
|
||||||
--timeout=9 \
|
--timeout=9 \
|
||||||
--durations=10 \
|
--durations=10 \
|
||||||
-n auto \
|
-n auto \
|
||||||
--dist=loadfile \
|
--dist=loadfile \
|
||||||
--test-group-count 4 \
|
--test-group-count ${{ needs.changes.outputs.test_group_count }} \
|
||||||
--test-group=${{ matrix.group }} \
|
--test-group=${{ matrix.group }} \
|
||||||
--cov homeassistant \
|
--cov homeassistant \
|
||||||
--cov-report= \
|
--cov-report=xml \
|
||||||
-o console_output_style=count \
|
-o console_output_style=count \
|
||||||
-p no:sugar \
|
-p no:sugar \
|
||||||
tests
|
tests
|
||||||
|
- name: Run pytest (partially)
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'false' && matrix.python-version != '3.8'
|
||||||
|
run: |
|
||||||
|
. venv/bin/activate
|
||||||
|
python3 -X dev -m pytest \
|
||||||
|
-qq \
|
||||||
|
--timeout=9 \
|
||||||
|
--durations=10 \
|
||||||
|
-n auto \
|
||||||
|
--cov homeassistant.components.${{ matrix.group }} \
|
||||||
|
--cov-report=xml \
|
||||||
|
--cov-report=term-missing \
|
||||||
|
-o console_output_style=count \
|
||||||
|
--durations=0 \
|
||||||
|
--durations-min=1 \
|
||||||
|
-p no:sugar \
|
||||||
|
tests/components/${{ matrix.group }}
|
||||||
|
- name: Run pytest (partially); no coverage
|
||||||
|
if: needs.changes.outputs.test_full_suite == 'false' && matrix.python-version == '3.8'
|
||||||
|
run: |
|
||||||
|
. venv/bin/activate
|
||||||
|
python3 -X dev -m pytest \
|
||||||
|
-qq \
|
||||||
|
--timeout=9 \
|
||||||
|
--durations=10 \
|
||||||
|
-n auto \
|
||||||
|
-o console_output_style=count \
|
||||||
|
--durations=0 \
|
||||||
|
--durations-min=1 \
|
||||||
|
-p no:sugar \
|
||||||
|
tests/components/${{ matrix.group }}
|
||||||
- name: Upload coverage artifact
|
- name: Upload coverage artifact
|
||||||
uses: actions/upload-artifact@v2.2.4
|
uses: actions/upload-artifact@v2.2.4
|
||||||
with:
|
with:
|
||||||
name: coverage-${{ matrix.python-version }}-group${{ matrix.group }}
|
name: coverage-${{ matrix.python-version }}-${{ matrix.group }}
|
||||||
path: .coverage
|
path: coverage.xml
|
||||||
- name: Check dirty
|
- name: Check dirty
|
||||||
run: |
|
run: |
|
||||||
./script/check_dirty
|
./script/check_dirty
|
||||||
|
|
||||||
coverage:
|
coverage:
|
||||||
name: Process test coverage
|
name: Upload test coverage to Codecov
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: ["prepare-tests", "pytest"]
|
needs:
|
||||||
strategy:
|
- changes
|
||||||
matrix:
|
- pytest
|
||||||
python-version: [3.8]
|
|
||||||
container: homeassistant/ci-azure:${{ matrix.python-version }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Check out code from GitHub
|
- name: Check out code from GitHub
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
- name: Restore full Python ${{ matrix.python-version }} virtual environment
|
|
||||||
id: cache-venv
|
|
||||||
uses: actions/cache@v2.1.6
|
|
||||||
with:
|
|
||||||
path: venv
|
|
||||||
key: ${{ runner.os }}-${{ matrix.python-version }}-${{
|
|
||||||
needs.prepare-tests.outputs.python-key }}
|
|
||||||
- name: Fail job if Python cache restore failed
|
|
||||||
if: steps.cache-venv.outputs.cache-hit != 'true'
|
|
||||||
run: |
|
|
||||||
echo "Failed to restore Python virtual environment from cache"
|
|
||||||
exit 1
|
|
||||||
- name: Download all coverage artifacts
|
- name: Download all coverage artifacts
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v2
|
||||||
- name: Combine coverage results
|
- name: Upload coverage to Codecov (full coverage)
|
||||||
run: |
|
if: needs.changes.outputs.test_full_suite == 'true'
|
||||||
. venv/bin/activate
|
uses: codecov/codecov-action@v2.1.0
|
||||||
coverage combine coverage*/.coverage*
|
with:
|
||||||
coverage report --fail-under=94
|
flags: full-suite
|
||||||
coverage xml
|
- name: Upload coverage to Codecov (partial coverage)
|
||||||
- name: Upload coverage to Codecov
|
if: needs.changes.outputs.test_full_suite == 'false'
|
||||||
uses: codecov/codecov-action@v2.1.0
|
uses: codecov/codecov-action@v2.1.0
|
||||||
|
18
.github/workflows/matchers/pytest-slow.json
vendored
Normal file
18
.github/workflows/matchers/pytest-slow.json
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"problemMatcher": [
|
||||||
|
{
|
||||||
|
"owner": "python",
|
||||||
|
"pattern": [
|
||||||
|
{
|
||||||
|
"regexp": "^=+ slowest durations =+$"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"regexp": "^((.*s)\\s(call|setup|teardown)\\s+(.*)::(.*))$",
|
||||||
|
"message": 1,
|
||||||
|
"file": 2,
|
||||||
|
"loop": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
8
.github/workflows/translations.yaml
vendored
8
.github/workflows/translations.yaml
vendored
@ -20,10 +20,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v2.3.1
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
|
|
||||||
@ -39,10 +39,10 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
- name: Set up Python ${{ env.DEFAULT_PYTHON }}
|
||||||
uses: actions/setup-python@v2.2.2
|
uses: actions/setup-python@v2.3.1
|
||||||
with:
|
with:
|
||||||
python-version: ${{ env.DEFAULT_PYTHON }}
|
python-version: ${{ env.DEFAULT_PYTHON }}
|
||||||
|
|
||||||
|
6
.github/workflows/wheels.yml
vendored
6
.github/workflows/wheels.yml
vendored
@ -21,7 +21,7 @@ jobs:
|
|||||||
architectures: ${{ steps.info.outputs.architectures }}
|
architectures: ${{ steps.info.outputs.architectures }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
- name: Get information
|
- name: Get information
|
||||||
id: info
|
id: info
|
||||||
@ -68,7 +68,7 @@ jobs:
|
|||||||
- "3.9-alpine3.14"
|
- "3.9-alpine3.14"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
- name: Download env_file
|
- name: Download env_file
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v2
|
||||||
@ -108,7 +108,7 @@ jobs:
|
|||||||
- "3.9-alpine3.14"
|
- "3.9-alpine3.14"
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout the repository
|
- name: Checkout the repository
|
||||||
uses: actions/checkout@v2.3.5
|
uses: actions/checkout@v2.4.0
|
||||||
|
|
||||||
- name: Download env_file
|
- name: Download env_file
|
||||||
uses: actions/download-artifact@v2
|
uses: actions/download-artifact@v2
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
repos:
|
repos:
|
||||||
- repo: https://github.com/asottile/pyupgrade
|
- repo: https://github.com/asottile/pyupgrade
|
||||||
rev: v2.27.0
|
rev: v2.29.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: pyupgrade
|
- id: pyupgrade
|
||||||
args: [--py38-plus]
|
args: [--py38-plus]
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 21.9b0
|
rev: 21.11b1
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
args:
|
args:
|
||||||
@ -17,7 +17,7 @@ repos:
|
|||||||
hooks:
|
hooks:
|
||||||
- id: codespell
|
- id: codespell
|
||||||
args:
|
args:
|
||||||
- --ignore-words-list=hass,alot,datas,dof,dur,ether,farenheit,hist,iff,ines,ist,lightsensor,mut,nd,pres,referer,ser,serie,te,technik,ue,uint,visability,wan,wanna,withing,iam,incomfort,ba
|
- --ignore-words-list=hass,alot,datas,dof,dur,ether,farenheit,hist,iff,ines,ist,lightsensor,mut,nd,pres,referer,ser,serie,te,technik,ue,uint,visability,wan,wanna,withing,iam,incomfort,ba,haa
|
||||||
- --skip="./.*,*.csv,*.json"
|
- --skip="./.*,*.csv,*.json"
|
||||||
- --quiet-level=2
|
- --quiet-level=2
|
||||||
exclude_types: [csv, json]
|
exclude_types: [csv, json]
|
||||||
@ -45,7 +45,7 @@ repos:
|
|||||||
- --configfile=tests/bandit.yaml
|
- --configfile=tests/bandit.yaml
|
||||||
files: ^(homeassistant|script|tests)/.+\.py$
|
files: ^(homeassistant|script|tests)/.+\.py$
|
||||||
- repo: https://github.com/PyCQA/isort
|
- repo: https://github.com/PyCQA/isort
|
||||||
rev: 5.9.3
|
rev: 5.10.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: isort
|
- id: isort
|
||||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||||
@ -61,7 +61,7 @@ repos:
|
|||||||
- --branch=master
|
- --branch=master
|
||||||
- --branch=rc
|
- --branch=rc
|
||||||
- repo: https://github.com/adrienverge/yamllint.git
|
- repo: https://github.com/adrienverge/yamllint.git
|
||||||
rev: v1.26.1
|
rev: v1.26.3
|
||||||
hooks:
|
hooks:
|
||||||
- id: yamllint
|
- id: yamllint
|
||||||
- repo: https://github.com/pre-commit/mirrors-prettier
|
- repo: https://github.com/pre-commit/mirrors-prettier
|
||||||
|
@ -24,6 +24,7 @@ homeassistant.components.bmw_connected_drive.*
|
|||||||
homeassistant.components.bond.*
|
homeassistant.components.bond.*
|
||||||
homeassistant.components.braviatv.*
|
homeassistant.components.braviatv.*
|
||||||
homeassistant.components.brother.*
|
homeassistant.components.brother.*
|
||||||
|
homeassistant.components.button.*
|
||||||
homeassistant.components.calendar.*
|
homeassistant.components.calendar.*
|
||||||
homeassistant.components.camera.*
|
homeassistant.components.camera.*
|
||||||
homeassistant.components.canary.*
|
homeassistant.components.canary.*
|
||||||
@ -32,6 +33,7 @@ homeassistant.components.crownstone.*
|
|||||||
homeassistant.components.device_automation.*
|
homeassistant.components.device_automation.*
|
||||||
homeassistant.components.device_tracker.*
|
homeassistant.components.device_tracker.*
|
||||||
homeassistant.components.devolo_home_control.*
|
homeassistant.components.devolo_home_control.*
|
||||||
|
homeassistant.components.devolo_home_network.*
|
||||||
homeassistant.components.dlna_dmr.*
|
homeassistant.components.dlna_dmr.*
|
||||||
homeassistant.components.dnsip.*
|
homeassistant.components.dnsip.*
|
||||||
homeassistant.components.dsmr.*
|
homeassistant.components.dsmr.*
|
||||||
@ -40,17 +42,20 @@ homeassistant.components.efergy.*
|
|||||||
homeassistant.components.elgato.*
|
homeassistant.components.elgato.*
|
||||||
homeassistant.components.esphome.*
|
homeassistant.components.esphome.*
|
||||||
homeassistant.components.energy.*
|
homeassistant.components.energy.*
|
||||||
|
homeassistant.components.evil_genius_labs.*
|
||||||
homeassistant.components.fastdotcom.*
|
homeassistant.components.fastdotcom.*
|
||||||
homeassistant.components.fitbit.*
|
homeassistant.components.fitbit.*
|
||||||
homeassistant.components.flunearyou.*
|
homeassistant.components.flunearyou.*
|
||||||
homeassistant.components.flux_led.*
|
homeassistant.components.flux_led.*
|
||||||
homeassistant.components.forecast_solar.*
|
homeassistant.components.forecast_solar.*
|
||||||
homeassistant.components.fritzbox.*
|
homeassistant.components.fritzbox.*
|
||||||
|
homeassistant.components.fronius.*
|
||||||
homeassistant.components.frontend.*
|
homeassistant.components.frontend.*
|
||||||
homeassistant.components.fritz.*
|
homeassistant.components.fritz.*
|
||||||
homeassistant.components.geo_location.*
|
homeassistant.components.geo_location.*
|
||||||
homeassistant.components.gios.*
|
homeassistant.components.gios.*
|
||||||
homeassistant.components.goalzero.*
|
homeassistant.components.goalzero.*
|
||||||
|
homeassistant.components.greeneye_monitor.*
|
||||||
homeassistant.components.group.*
|
homeassistant.components.group.*
|
||||||
homeassistant.components.guardian.*
|
homeassistant.components.guardian.*
|
||||||
homeassistant.components.history.*
|
homeassistant.components.history.*
|
||||||
@ -62,6 +67,7 @@ homeassistant.components.image_processing.*
|
|||||||
homeassistant.components.input_select.*
|
homeassistant.components.input_select.*
|
||||||
homeassistant.components.integration.*
|
homeassistant.components.integration.*
|
||||||
homeassistant.components.iqvia.*
|
homeassistant.components.iqvia.*
|
||||||
|
homeassistant.components.jellyfin.*
|
||||||
homeassistant.components.jewish_calendar.*
|
homeassistant.components.jewish_calendar.*
|
||||||
homeassistant.components.knx.*
|
homeassistant.components.knx.*
|
||||||
homeassistant.components.kraken.*
|
homeassistant.components.kraken.*
|
||||||
@ -93,12 +99,14 @@ homeassistant.components.persistent_notification.*
|
|||||||
homeassistant.components.pi_hole.*
|
homeassistant.components.pi_hole.*
|
||||||
homeassistant.components.proximity.*
|
homeassistant.components.proximity.*
|
||||||
homeassistant.components.rainmachine.*
|
homeassistant.components.rainmachine.*
|
||||||
|
homeassistant.components.rdw.*
|
||||||
homeassistant.components.recollect_waste.*
|
homeassistant.components.recollect_waste.*
|
||||||
homeassistant.components.recorder.purge
|
homeassistant.components.recorder.purge
|
||||||
homeassistant.components.recorder.repack
|
homeassistant.components.recorder.repack
|
||||||
homeassistant.components.recorder.statistics
|
homeassistant.components.recorder.statistics
|
||||||
homeassistant.components.remote.*
|
homeassistant.components.remote.*
|
||||||
homeassistant.components.renault.*
|
homeassistant.components.renault.*
|
||||||
|
homeassistant.components.ridwell.*
|
||||||
homeassistant.components.rituals_perfume_genie.*
|
homeassistant.components.rituals_perfume_genie.*
|
||||||
homeassistant.components.rpi_power.*
|
homeassistant.components.rpi_power.*
|
||||||
homeassistant.components.samsungtv.*
|
homeassistant.components.samsungtv.*
|
||||||
@ -119,18 +127,24 @@ homeassistant.components.switcher_kis.*
|
|||||||
homeassistant.components.synology_dsm.*
|
homeassistant.components.synology_dsm.*
|
||||||
homeassistant.components.systemmonitor.*
|
homeassistant.components.systemmonitor.*
|
||||||
homeassistant.components.tag.*
|
homeassistant.components.tag.*
|
||||||
|
homeassistant.components.tailscale.*
|
||||||
homeassistant.components.tautulli.*
|
homeassistant.components.tautulli.*
|
||||||
homeassistant.components.tcp.*
|
homeassistant.components.tcp.*
|
||||||
homeassistant.components.tile.*
|
homeassistant.components.tile.*
|
||||||
homeassistant.components.tplink.*
|
homeassistant.components.tplink.*
|
||||||
|
homeassistant.components.tolo.*
|
||||||
homeassistant.components.tractive.*
|
homeassistant.components.tractive.*
|
||||||
homeassistant.components.tradfri.*
|
homeassistant.components.tradfri.*
|
||||||
homeassistant.components.tts.*
|
homeassistant.components.tts.*
|
||||||
|
homeassistant.components.twentemilieu.*
|
||||||
homeassistant.components.upcloud.*
|
homeassistant.components.upcloud.*
|
||||||
homeassistant.components.uptime.*
|
homeassistant.components.uptime.*
|
||||||
homeassistant.components.uptimerobot.*
|
homeassistant.components.uptimerobot.*
|
||||||
homeassistant.components.vacuum.*
|
homeassistant.components.vacuum.*
|
||||||
homeassistant.components.vallox.*
|
homeassistant.components.vallox.*
|
||||||
|
homeassistant.components.velbus.*
|
||||||
|
homeassistant.components.vlc_telnet.*
|
||||||
|
homeassistant.components.wallbox.*
|
||||||
homeassistant.components.water_heater.*
|
homeassistant.components.water_heater.*
|
||||||
homeassistant.components.watttime.*
|
homeassistant.components.watttime.*
|
||||||
homeassistant.components.weather.*
|
homeassistant.components.weather.*
|
||||||
|
2
.vscode/tasks.json
vendored
2
.vscode/tasks.json
vendored
@ -64,7 +64,7 @@
|
|||||||
"label": "Code Coverage",
|
"label": "Code Coverage",
|
||||||
"detail": "Generate code coverage report for a given integration.",
|
"detail": "Generate code coverage report for a given integration.",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"command": "pytest ./tests/components/${input:integrationName}/ --cov=homeassistant.components.${input:integrationName} --cov-report term-missing",
|
"command": "pytest ./tests/components/${input:integrationName}/ --cov=homeassistant.components.${input:integrationName} --cov-report term-missing --durations-min=1 --durations=0",
|
||||||
"group": {
|
"group": {
|
||||||
"kind": "test",
|
"kind": "test",
|
||||||
"isDefault": true
|
"isDefault": true
|
||||||
|
18
CODEOWNERS
18
CODEOWNERS
@ -67,12 +67,14 @@ homeassistant/components/axis/* @Kane610
|
|||||||
homeassistant/components/azure_devops/* @timmo001
|
homeassistant/components/azure_devops/* @timmo001
|
||||||
homeassistant/components/azure_event_hub/* @eavanvalkenburg
|
homeassistant/components/azure_event_hub/* @eavanvalkenburg
|
||||||
homeassistant/components/azure_service_bus/* @hfurubotten
|
homeassistant/components/azure_service_bus/* @hfurubotten
|
||||||
|
homeassistant/components/balboa/* @garbled1
|
||||||
homeassistant/components/beewi_smartclim/* @alemuro
|
homeassistant/components/beewi_smartclim/* @alemuro
|
||||||
homeassistant/components/bitcoin/* @fabaff
|
homeassistant/components/bitcoin/* @fabaff
|
||||||
homeassistant/components/bizkaibus/* @UgaitzEtxebarria
|
homeassistant/components/bizkaibus/* @UgaitzEtxebarria
|
||||||
homeassistant/components/blebox/* @bbx-a @bbx-jp
|
homeassistant/components/blebox/* @bbx-a @bbx-jp
|
||||||
homeassistant/components/blink/* @fronzbot
|
homeassistant/components/blink/* @fronzbot
|
||||||
homeassistant/components/blueprint/* @home-assistant/core
|
homeassistant/components/blueprint/* @home-assistant/core
|
||||||
|
homeassistant/components/bluesound/* @thrawnarn
|
||||||
homeassistant/components/bmp280/* @belidzs
|
homeassistant/components/bmp280/* @belidzs
|
||||||
homeassistant/components/bmw_connected_drive/* @gerard33 @rikroe
|
homeassistant/components/bmw_connected_drive/* @gerard33 @rikroe
|
||||||
homeassistant/components/bond/* @bdraco @prystupa @joshs85
|
homeassistant/components/bond/* @bdraco @prystupa @joshs85
|
||||||
@ -84,6 +86,7 @@ homeassistant/components/brunt/* @eavanvalkenburg
|
|||||||
homeassistant/components/bsblan/* @liudger
|
homeassistant/components/bsblan/* @liudger
|
||||||
homeassistant/components/bt_smarthub/* @jxwolstenholme
|
homeassistant/components/bt_smarthub/* @jxwolstenholme
|
||||||
homeassistant/components/buienradar/* @mjj4791 @ties @Robbie1221
|
homeassistant/components/buienradar/* @mjj4791 @ties @Robbie1221
|
||||||
|
homeassistant/components/button/* @home-assistant/core
|
||||||
homeassistant/components/cast/* @emontnemery
|
homeassistant/components/cast/* @emontnemery
|
||||||
homeassistant/components/cert_expiry/* @Cereal2nd @jjlawren
|
homeassistant/components/cert_expiry/* @Cereal2nd @jjlawren
|
||||||
homeassistant/components/circuit/* @braam
|
homeassistant/components/circuit/* @braam
|
||||||
@ -118,6 +121,7 @@ homeassistant/components/denonavr/* @ol-iver @starkillerOG
|
|||||||
homeassistant/components/derivative/* @afaucogney
|
homeassistant/components/derivative/* @afaucogney
|
||||||
homeassistant/components/device_automation/* @home-assistant/core
|
homeassistant/components/device_automation/* @home-assistant/core
|
||||||
homeassistant/components/devolo_home_control/* @2Fake @Shutgun
|
homeassistant/components/devolo_home_control/* @2Fake @Shutgun
|
||||||
|
homeassistant/components/devolo_home_network/* @2Fake @Shutgun
|
||||||
homeassistant/components/dexcom/* @gagebenne
|
homeassistant/components/dexcom/* @gagebenne
|
||||||
homeassistant/components/dhcp/* @bdraco
|
homeassistant/components/dhcp/* @bdraco
|
||||||
homeassistant/components/dht/* @thegardenmonkey
|
homeassistant/components/dht/* @thegardenmonkey
|
||||||
@ -157,6 +161,7 @@ homeassistant/components/epson/* @pszafer
|
|||||||
homeassistant/components/epsonworkforce/* @ThaStealth
|
homeassistant/components/epsonworkforce/* @ThaStealth
|
||||||
homeassistant/components/eq3btsmart/* @rytilahti
|
homeassistant/components/eq3btsmart/* @rytilahti
|
||||||
homeassistant/components/esphome/* @OttoWinter @jesserockz
|
homeassistant/components/esphome/* @OttoWinter @jesserockz
|
||||||
|
homeassistant/components/evil_genius_labs/* @balloob
|
||||||
homeassistant/components/evohome/* @zxdavb
|
homeassistant/components/evohome/* @zxdavb
|
||||||
homeassistant/components/ezviz/* @RenierM26 @baqs
|
homeassistant/components/ezviz/* @RenierM26 @baqs
|
||||||
homeassistant/components/faa_delays/* @ntilley905
|
homeassistant/components/faa_delays/* @ntilley905
|
||||||
@ -182,7 +187,7 @@ homeassistant/components/freebox/* @hacf-fr @Quentame
|
|||||||
homeassistant/components/freedompro/* @stefano055415
|
homeassistant/components/freedompro/* @stefano055415
|
||||||
homeassistant/components/fritz/* @mammuth @AaronDavidSchneider @chemelli74
|
homeassistant/components/fritz/* @mammuth @AaronDavidSchneider @chemelli74
|
||||||
homeassistant/components/fritzbox/* @mib1185 @flabbamann
|
homeassistant/components/fritzbox/* @mib1185 @flabbamann
|
||||||
homeassistant/components/fronius/* @nielstron
|
homeassistant/components/fronius/* @nielstron @farmio
|
||||||
homeassistant/components/frontend/* @home-assistant/frontend
|
homeassistant/components/frontend/* @home-assistant/frontend
|
||||||
homeassistant/components/garages_amsterdam/* @klaasnicolaas
|
homeassistant/components/garages_amsterdam/* @klaasnicolaas
|
||||||
homeassistant/components/gdacs/* @exxamalte
|
homeassistant/components/gdacs/* @exxamalte
|
||||||
@ -227,7 +232,7 @@ homeassistant/components/homematic/* @pvizeli @danielperna84
|
|||||||
homeassistant/components/honeywell/* @rdfurman
|
homeassistant/components/honeywell/* @rdfurman
|
||||||
homeassistant/components/http/* @home-assistant/core
|
homeassistant/components/http/* @home-assistant/core
|
||||||
homeassistant/components/huawei_lte/* @scop @fphammerle
|
homeassistant/components/huawei_lte/* @scop @fphammerle
|
||||||
homeassistant/components/hue/* @balloob @frenck
|
homeassistant/components/hue/* @balloob @marcelveldt
|
||||||
homeassistant/components/huisbaasje/* @dennisschroer
|
homeassistant/components/huisbaasje/* @dennisschroer
|
||||||
homeassistant/components/humidifier/* @home-assistant/core @Shulyaka
|
homeassistant/components/humidifier/* @home-assistant/core @Shulyaka
|
||||||
homeassistant/components/hunterdouglas_powerview/* @bdraco
|
homeassistant/components/hunterdouglas_powerview/* @bdraco
|
||||||
@ -261,6 +266,7 @@ homeassistant/components/irish_rail_transport/* @ttroy50
|
|||||||
homeassistant/components/islamic_prayer_times/* @engrbm87
|
homeassistant/components/islamic_prayer_times/* @engrbm87
|
||||||
homeassistant/components/isy994/* @bdraco @shbatm
|
homeassistant/components/isy994/* @bdraco @shbatm
|
||||||
homeassistant/components/izone/* @Swamp-Ig
|
homeassistant/components/izone/* @Swamp-Ig
|
||||||
|
homeassistant/components/jellyfin/* @j-stienstra
|
||||||
homeassistant/components/jewish_calendar/* @tsvi
|
homeassistant/components/jewish_calendar/* @tsvi
|
||||||
homeassistant/components/juicenet/* @jesserockz
|
homeassistant/components/juicenet/* @jesserockz
|
||||||
homeassistant/components/kaiterra/* @Michsior14
|
homeassistant/components/kaiterra/* @Michsior14
|
||||||
@ -287,7 +293,6 @@ homeassistant/components/local_ip/* @issacg
|
|||||||
homeassistant/components/logger/* @home-assistant/core
|
homeassistant/components/logger/* @home-assistant/core
|
||||||
homeassistant/components/logi_circle/* @evanjd
|
homeassistant/components/logi_circle/* @evanjd
|
||||||
homeassistant/components/lookin/* @ANMalko
|
homeassistant/components/lookin/* @ANMalko
|
||||||
homeassistant/components/loopenergy/* @pavoni
|
|
||||||
homeassistant/components/lovelace/* @home-assistant/frontend
|
homeassistant/components/lovelace/* @home-assistant/frontend
|
||||||
homeassistant/components/luci/* @mzdrale
|
homeassistant/components/luci/* @mzdrale
|
||||||
homeassistant/components/luftdaten/* @fabaff
|
homeassistant/components/luftdaten/* @fabaff
|
||||||
@ -422,6 +427,7 @@ homeassistant/components/raincloud/* @vanstinator
|
|||||||
homeassistant/components/rainforest_eagle/* @gtdiehl @jcalbert
|
homeassistant/components/rainforest_eagle/* @gtdiehl @jcalbert
|
||||||
homeassistant/components/rainmachine/* @bachya
|
homeassistant/components/rainmachine/* @bachya
|
||||||
homeassistant/components/random/* @fabaff
|
homeassistant/components/random/* @fabaff
|
||||||
|
homeassistant/components/rdw/* @frenck
|
||||||
homeassistant/components/recollect_waste/* @bachya
|
homeassistant/components/recollect_waste/* @bachya
|
||||||
homeassistant/components/recorder/* @home-assistant/core
|
homeassistant/components/recorder/* @home-assistant/core
|
||||||
homeassistant/components/rejseplanen/* @DarkFox
|
homeassistant/components/rejseplanen/* @DarkFox
|
||||||
@ -429,6 +435,7 @@ homeassistant/components/renault/* @epenet
|
|||||||
homeassistant/components/repetier/* @MTrab
|
homeassistant/components/repetier/* @MTrab
|
||||||
homeassistant/components/rflink/* @javicalle
|
homeassistant/components/rflink/* @javicalle
|
||||||
homeassistant/components/rfxtrx/* @danielhiversen @elupus @RobBie1221
|
homeassistant/components/rfxtrx/* @danielhiversen @elupus @RobBie1221
|
||||||
|
homeassistant/components/ridwell/* @bachya
|
||||||
homeassistant/components/ring/* @balloob
|
homeassistant/components/ring/* @balloob
|
||||||
homeassistant/components/risco/* @OnFreund
|
homeassistant/components/risco/* @OnFreund
|
||||||
homeassistant/components/rituals_perfume_genie/* @milanmeu
|
homeassistant/components/rituals_perfume_genie/* @milanmeu
|
||||||
@ -520,12 +527,14 @@ homeassistant/components/system_bridge/* @timmo001
|
|||||||
homeassistant/components/tado/* @michaelarnauts @noltari
|
homeassistant/components/tado/* @michaelarnauts @noltari
|
||||||
homeassistant/components/tag/* @balloob @dmulcahey
|
homeassistant/components/tag/* @balloob @dmulcahey
|
||||||
homeassistant/components/tahoma/* @philklei
|
homeassistant/components/tahoma/* @philklei
|
||||||
|
homeassistant/components/tailscale/* @frenck
|
||||||
homeassistant/components/tankerkoenig/* @guillempages
|
homeassistant/components/tankerkoenig/* @guillempages
|
||||||
homeassistant/components/tapsaff/* @bazwilliams
|
homeassistant/components/tapsaff/* @bazwilliams
|
||||||
homeassistant/components/tasmota/* @emontnemery
|
homeassistant/components/tasmota/* @emontnemery
|
||||||
homeassistant/components/tautulli/* @ludeeus
|
homeassistant/components/tautulli/* @ludeeus
|
||||||
homeassistant/components/tellduslive/* @fredrike
|
homeassistant/components/tellduslive/* @fredrike
|
||||||
homeassistant/components/template/* @PhracturedBlue @tetienne @home-assistant/core
|
homeassistant/components/template/* @PhracturedBlue @tetienne @home-assistant/core
|
||||||
|
homeassistant/components/tesla_wall_connector/* @einarhauks
|
||||||
homeassistant/components/tfiac/* @fredrike @mellado
|
homeassistant/components/tfiac/* @fredrike @mellado
|
||||||
homeassistant/components/thethingsnetwork/* @fabaff
|
homeassistant/components/thethingsnetwork/* @fabaff
|
||||||
homeassistant/components/threshold/* @fabaff
|
homeassistant/components/threshold/* @fabaff
|
||||||
@ -534,12 +543,12 @@ homeassistant/components/tile/* @bachya
|
|||||||
homeassistant/components/time_date/* @fabaff
|
homeassistant/components/time_date/* @fabaff
|
||||||
homeassistant/components/tmb/* @alemuro
|
homeassistant/components/tmb/* @alemuro
|
||||||
homeassistant/components/todoist/* @boralyl
|
homeassistant/components/todoist/* @boralyl
|
||||||
|
homeassistant/components/tolo/* @MatthiasLohr
|
||||||
homeassistant/components/totalconnect/* @austinmroczek
|
homeassistant/components/totalconnect/* @austinmroczek
|
||||||
homeassistant/components/tplink/* @rytilahti @thegardenmonkey
|
homeassistant/components/tplink/* @rytilahti @thegardenmonkey
|
||||||
homeassistant/components/traccar/* @ludeeus
|
homeassistant/components/traccar/* @ludeeus
|
||||||
homeassistant/components/trace/* @home-assistant/core
|
homeassistant/components/trace/* @home-assistant/core
|
||||||
homeassistant/components/tractive/* @Danielhiversen @zhulik @bieniu
|
homeassistant/components/tractive/* @Danielhiversen @zhulik @bieniu
|
||||||
homeassistant/components/tradfri/* @janiversen
|
|
||||||
homeassistant/components/trafikverket_train/* @endor-force
|
homeassistant/components/trafikverket_train/* @endor-force
|
||||||
homeassistant/components/trafikverket_weatherstation/* @endor-force
|
homeassistant/components/trafikverket_weatherstation/* @endor-force
|
||||||
homeassistant/components/transmission/* @engrbm87 @JPHutchins
|
homeassistant/components/transmission/* @engrbm87 @JPHutchins
|
||||||
@ -575,6 +584,7 @@ homeassistant/components/vizio/* @raman325
|
|||||||
homeassistant/components/vlc_telnet/* @rodripf @dmcc @MartinHjelmare
|
homeassistant/components/vlc_telnet/* @rodripf @dmcc @MartinHjelmare
|
||||||
homeassistant/components/volkszaehler/* @fabaff
|
homeassistant/components/volkszaehler/* @fabaff
|
||||||
homeassistant/components/volumio/* @OnFreund
|
homeassistant/components/volumio/* @OnFreund
|
||||||
|
homeassistant/components/volvooncall/* @molobrakos @decompil3d
|
||||||
homeassistant/components/wake_on_lan/* @ntilley905
|
homeassistant/components/wake_on_lan/* @ntilley905
|
||||||
homeassistant/components/wallbox/* @hesselonline
|
homeassistant/components/wallbox/* @hesselonline
|
||||||
homeassistant/components/waqi/* @andrey-git
|
homeassistant/components/waqi/* @andrey-git
|
||||||
|
15
Dockerfile
15
Dockerfile
@ -7,12 +7,21 @@ ENV \
|
|||||||
|
|
||||||
WORKDIR /usr/src
|
WORKDIR /usr/src
|
||||||
|
|
||||||
## Setup Home Assistant
|
## Setup Home Assistant Core dependencies
|
||||||
|
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}" \
|
||||||
|
-r homeassistant/requirements.txt
|
||||||
|
COPY requirements_all.txt homeassistant/
|
||||||
|
RUN \
|
||||||
|
pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \
|
||||||
|
-r homeassistant/requirements_all.txt
|
||||||
|
|
||||||
|
## Setup Home Assistant Core
|
||||||
COPY . homeassistant/
|
COPY . homeassistant/
|
||||||
RUN \
|
RUN \
|
||||||
pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \
|
pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \
|
||||||
-r homeassistant/requirements_all.txt \
|
|
||||||
&& pip3 install --no-cache-dir --no-index --only-binary=:all: --find-links "${WHEELS_LINKS}" \
|
|
||||||
-e ./homeassistant \
|
-e ./homeassistant \
|
||||||
&& python3 -m compileall homeassistant/homeassistant
|
&& python3 -m compileall homeassistant/homeassistant
|
||||||
|
|
||||||
|
@ -30,11 +30,12 @@ RUN git clone --depth 1 https://github.com/home-assistant/hass-release \
|
|||||||
WORKDIR /workspaces
|
WORKDIR /workspaces
|
||||||
|
|
||||||
# Install Python dependencies from requirements
|
# Install Python dependencies from requirements
|
||||||
COPY requirements.txt requirements_test.txt requirements_test_pre_commit.txt ./
|
COPY requirements.txt ./
|
||||||
COPY homeassistant/package_constraints.txt homeassistant/package_constraints.txt
|
COPY homeassistant/package_constraints.txt homeassistant/package_constraints.txt
|
||||||
RUN pip3 install -r requirements.txt \
|
RUN pip3 install -r requirements.txt
|
||||||
&& pip3 install -r requirements_test.txt \
|
COPY requirements_test.txt requirements_test_pre_commit.txt ./
|
||||||
&& rm -rf requirements.txt requirements_test.txt requirements_test_pre_commit.txt homeassistant/
|
RUN pip3 install -r requirements_test.txt
|
||||||
|
RUN rm -rf requirements.txt requirements_test.txt requirements_test_pre_commit.txt homeassistant/
|
||||||
|
|
||||||
# Set the default shell to bash instead of sh
|
# Set the default shell to bash instead of sh
|
||||||
ENV SHELL /bin/bash
|
ENV SHELL /bin/bash
|
||||||
|
22
build.json
22
build.json
@ -1,22 +0,0 @@
|
|||||||
{
|
|
||||||
"image": "homeassistant/{arch}-homeassistant",
|
|
||||||
"shadow_repository": "ghcr.io/home-assistant",
|
|
||||||
"build_from": {
|
|
||||||
"aarch64": "ghcr.io/home-assistant/aarch64-homeassistant-base:2021.09.0",
|
|
||||||
"armhf": "ghcr.io/home-assistant/armhf-homeassistant-base:2021.09.0",
|
|
||||||
"armv7": "ghcr.io/home-assistant/armv7-homeassistant-base:2021.09.0",
|
|
||||||
"amd64": "ghcr.io/home-assistant/amd64-homeassistant-base:2021.09.0",
|
|
||||||
"i386": "ghcr.io/home-assistant/i386-homeassistant-base:2021.09.0"
|
|
||||||
},
|
|
||||||
"labels": {
|
|
||||||
"io.hass.type": "core",
|
|
||||||
"org.opencontainers.image.title": "Home Assistant",
|
|
||||||
"org.opencontainers.image.description": "Open-source home automation platform running on Python 3",
|
|
||||||
"org.opencontainers.image.source": "https://github.com/home-assistant/core",
|
|
||||||
"org.opencontainers.image.authors": "The Home Assistant Authors",
|
|
||||||
"org.opencontainers.image.url": "https://www.home-assistant.io/",
|
|
||||||
"org.opencontainers.image.documentation": "https://www.home-assistant.io/docs/",
|
|
||||||
"org.opencontainers.image.licenses": "Apache License 2.0"
|
|
||||||
},
|
|
||||||
"version_tag": true
|
|
||||||
}
|
|
20
build.yaml
Normal file
20
build.yaml
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
image: homeassistant/{arch}-homeassistant
|
||||||
|
shadow_repository: ghcr.io/home-assistant
|
||||||
|
build_from:
|
||||||
|
aarch64: ghcr.io/home-assistant/aarch64-homeassistant-base:2021.09.0
|
||||||
|
armhf: ghcr.io/home-assistant/armhf-homeassistant-base:2021.09.0
|
||||||
|
armv7: ghcr.io/home-assistant/armv7-homeassistant-base:2021.09.0
|
||||||
|
amd64: ghcr.io/home-assistant/amd64-homeassistant-base:2021.09.0
|
||||||
|
i386: ghcr.io/home-assistant/i386-homeassistant-base:2021.09.0
|
||||||
|
codenotary:
|
||||||
|
signer: notary@home-assistant.io
|
||||||
|
base_image: notary@home-assistant.io
|
||||||
|
labels:
|
||||||
|
io.hass.type: core
|
||||||
|
org.opencontainers.image.title: Home Assistant
|
||||||
|
org.opencontainers.image.description: Open-source home automation platform running on Python 3
|
||||||
|
org.opencontainers.image.source: https://github.com/home-assistant/core
|
||||||
|
org.opencontainers.image.authors: The Home Assistant Authors
|
||||||
|
org.opencontainers.image.url: https://www.home-assistant.io/
|
||||||
|
org.opencontainers.image.documentation: https://www.home-assistant.io/docs/
|
||||||
|
org.opencontainers.image.licenses: Apache License 2.0
|
24
codecov.yml
24
codecov.yml
@ -6,4 +6,28 @@ coverage:
|
|||||||
default:
|
default:
|
||||||
target: 90
|
target: 90
|
||||||
threshold: 0.09
|
threshold: 0.09
|
||||||
|
config-flows:
|
||||||
|
target: auto
|
||||||
|
threshold: 0
|
||||||
|
paths:
|
||||||
|
- homeassistant/components/*/config_flow.py
|
||||||
|
patch:
|
||||||
|
default:
|
||||||
|
target: auto
|
||||||
|
config-flows:
|
||||||
|
target: 100
|
||||||
|
threshold: 0
|
||||||
|
paths:
|
||||||
|
- homeassistant/components/*/config_flow.py
|
||||||
comment: false
|
comment: false
|
||||||
|
|
||||||
|
# To make partial tests possible,
|
||||||
|
# we need to carry forward.
|
||||||
|
flag_management:
|
||||||
|
default_rules:
|
||||||
|
carryforward: false
|
||||||
|
individual_flags:
|
||||||
|
- name: full-suite
|
||||||
|
paths:
|
||||||
|
- ".*"
|
||||||
|
carryforward: true
|
||||||
|
42
homeassistant/async_timeout_backcompat.py
Normal file
42
homeassistant/async_timeout_backcompat.py
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
"""Provide backwards compat for async_timeout."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import asyncio
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
import async_timeout
|
||||||
|
|
||||||
|
from homeassistant.helpers.frame import report
|
||||||
|
|
||||||
|
|
||||||
|
def timeout(
|
||||||
|
delay: float | None, loop: asyncio.AbstractEventLoop | None = None
|
||||||
|
) -> async_timeout.Timeout:
|
||||||
|
"""Backwards compatible timeout context manager that warns with loop usage."""
|
||||||
|
if loop is None:
|
||||||
|
loop = asyncio.get_running_loop()
|
||||||
|
else:
|
||||||
|
report(
|
||||||
|
"called async_timeout.timeout with loop keyword argument. The loop keyword argument is deprecated and calls will fail after Home Assistant 2022.2",
|
||||||
|
error_if_core=False,
|
||||||
|
)
|
||||||
|
if delay is not None:
|
||||||
|
deadline: float | None = loop.time() + delay
|
||||||
|
else:
|
||||||
|
deadline = None
|
||||||
|
return async_timeout.Timeout(deadline, loop)
|
||||||
|
|
||||||
|
|
||||||
|
def current_task(loop: asyncio.AbstractEventLoop) -> asyncio.Task[Any] | None:
|
||||||
|
"""Backwards compatible current_task."""
|
||||||
|
report(
|
||||||
|
"called async_timeout.current_task. The current_task call is deprecated and calls will fail after Home Assistant 2022.2; use asyncio.current_task instead",
|
||||||
|
error_if_core=False,
|
||||||
|
)
|
||||||
|
return asyncio.current_task()
|
||||||
|
|
||||||
|
|
||||||
|
def enable() -> None:
|
||||||
|
"""Enable backwards compat transitions."""
|
||||||
|
async_timeout.timeout = timeout
|
||||||
|
async_timeout.current_task = current_task # type: ignore[attr-defined]
|
@ -214,11 +214,19 @@ class AuthManager:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
async def async_create_system_user(
|
async def async_create_system_user(
|
||||||
self, name: str, group_ids: list[str] | None = None
|
self,
|
||||||
|
name: str,
|
||||||
|
*,
|
||||||
|
group_ids: list[str] | None = None,
|
||||||
|
local_only: bool | None = None,
|
||||||
) -> models.User:
|
) -> models.User:
|
||||||
"""Create a system user."""
|
"""Create a system user."""
|
||||||
user = await self._store.async_create_user(
|
user = await self._store.async_create_user(
|
||||||
name=name, system_generated=True, is_active=True, group_ids=group_ids or []
|
name=name,
|
||||||
|
system_generated=True,
|
||||||
|
is_active=True,
|
||||||
|
group_ids=group_ids or [],
|
||||||
|
local_only=local_only,
|
||||||
)
|
)
|
||||||
|
|
||||||
self.hass.bus.async_fire(EVENT_USER_ADDED, {"user_id": user.id})
|
self.hass.bus.async_fire(EVENT_USER_ADDED, {"user_id": user.id})
|
||||||
@ -226,13 +234,18 @@ class AuthManager:
|
|||||||
return user
|
return user
|
||||||
|
|
||||||
async def async_create_user(
|
async def async_create_user(
|
||||||
self, name: str, group_ids: list[str] | None = None
|
self,
|
||||||
|
name: str,
|
||||||
|
*,
|
||||||
|
group_ids: list[str] | None = None,
|
||||||
|
local_only: bool | None = None,
|
||||||
) -> models.User:
|
) -> models.User:
|
||||||
"""Create a user."""
|
"""Create a user."""
|
||||||
kwargs: dict[str, Any] = {
|
kwargs: dict[str, Any] = {
|
||||||
"name": name,
|
"name": name,
|
||||||
"is_active": True,
|
"is_active": True,
|
||||||
"group_ids": group_ids or [],
|
"group_ids": group_ids or [],
|
||||||
|
"local_only": local_only,
|
||||||
}
|
}
|
||||||
|
|
||||||
if await self._user_should_be_owner():
|
if await self._user_should_be_owner():
|
||||||
@ -304,13 +317,18 @@ class AuthManager:
|
|||||||
name: str | None = None,
|
name: str | None = None,
|
||||||
is_active: bool | None = None,
|
is_active: bool | None = None,
|
||||||
group_ids: list[str] | None = None,
|
group_ids: list[str] | None = None,
|
||||||
|
local_only: bool | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Update a user."""
|
"""Update a user."""
|
||||||
kwargs: dict[str, Any] = {}
|
kwargs: dict[str, Any] = {}
|
||||||
if name is not None:
|
|
||||||
kwargs["name"] = name
|
for attr_name, value in (
|
||||||
if group_ids is not None:
|
("name", name),
|
||||||
kwargs["group_ids"] = group_ids
|
("group_ids", group_ids),
|
||||||
|
("local_only", local_only),
|
||||||
|
):
|
||||||
|
if value is not None:
|
||||||
|
kwargs[attr_name] = value
|
||||||
await self._store.async_update_user(user, **kwargs)
|
await self._store.async_update_user(user, **kwargs)
|
||||||
|
|
||||||
if is_active is not None:
|
if is_active is not None:
|
||||||
|
@ -42,7 +42,7 @@ class AuthStore:
|
|||||||
self._groups: dict[str, models.Group] | None = None
|
self._groups: dict[str, models.Group] | None = None
|
||||||
self._perm_lookup: PermissionLookup | None = None
|
self._perm_lookup: PermissionLookup | None = None
|
||||||
self._store = hass.helpers.storage.Store(
|
self._store = hass.helpers.storage.Store(
|
||||||
STORAGE_VERSION, STORAGE_KEY, private=True
|
STORAGE_VERSION, STORAGE_KEY, private=True, atomic_writes=True
|
||||||
)
|
)
|
||||||
self._lock = asyncio.Lock()
|
self._lock = asyncio.Lock()
|
||||||
|
|
||||||
@ -86,6 +86,7 @@ class AuthStore:
|
|||||||
system_generated: bool | None = None,
|
system_generated: bool | None = None,
|
||||||
credentials: models.Credentials | None = None,
|
credentials: models.Credentials | None = None,
|
||||||
group_ids: list[str] | None = None,
|
group_ids: list[str] | None = None,
|
||||||
|
local_only: bool | None = None,
|
||||||
) -> models.User:
|
) -> models.User:
|
||||||
"""Create a new user."""
|
"""Create a new user."""
|
||||||
if self._users is None:
|
if self._users is None:
|
||||||
@ -108,14 +109,14 @@ class AuthStore:
|
|||||||
"perm_lookup": self._perm_lookup,
|
"perm_lookup": self._perm_lookup,
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_owner is not None:
|
for attr_name, value in (
|
||||||
kwargs["is_owner"] = is_owner
|
("is_owner", is_owner),
|
||||||
|
("is_active", is_active),
|
||||||
if is_active is not None:
|
("local_only", local_only),
|
||||||
kwargs["is_active"] = is_active
|
("system_generated", system_generated),
|
||||||
|
):
|
||||||
if system_generated is not None:
|
if value is not None:
|
||||||
kwargs["system_generated"] = system_generated
|
kwargs[attr_name] = value
|
||||||
|
|
||||||
new_user = models.User(**kwargs)
|
new_user = models.User(**kwargs)
|
||||||
|
|
||||||
@ -152,6 +153,7 @@ class AuthStore:
|
|||||||
name: str | None = None,
|
name: str | None = None,
|
||||||
is_active: bool | None = None,
|
is_active: bool | None = None,
|
||||||
group_ids: list[str] | None = None,
|
group_ids: list[str] | None = None,
|
||||||
|
local_only: bool | None = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""Update a user."""
|
"""Update a user."""
|
||||||
assert self._groups is not None
|
assert self._groups is not None
|
||||||
@ -166,7 +168,11 @@ class AuthStore:
|
|||||||
user.groups = groups
|
user.groups = groups
|
||||||
user.invalidate_permission_cache()
|
user.invalidate_permission_cache()
|
||||||
|
|
||||||
for attr_name, value in (("name", name), ("is_active", is_active)):
|
for attr_name, value in (
|
||||||
|
("name", name),
|
||||||
|
("is_active", is_active),
|
||||||
|
("local_only", local_only),
|
||||||
|
):
|
||||||
if value is not None:
|
if value is not None:
|
||||||
setattr(user, attr_name, value)
|
setattr(user, attr_name, value)
|
||||||
|
|
||||||
@ -417,6 +423,8 @@ class AuthStore:
|
|||||||
is_active=user_dict["is_active"],
|
is_active=user_dict["is_active"],
|
||||||
system_generated=user_dict["system_generated"],
|
system_generated=user_dict["system_generated"],
|
||||||
perm_lookup=perm_lookup,
|
perm_lookup=perm_lookup,
|
||||||
|
# New in 2021.11
|
||||||
|
local_only=user_dict.get("local_only", False),
|
||||||
)
|
)
|
||||||
|
|
||||||
for cred_dict in data["credentials"]:
|
for cred_dict in data["credentials"]:
|
||||||
@ -502,6 +510,7 @@ class AuthStore:
|
|||||||
"is_active": user.is_active,
|
"is_active": user.is_active,
|
||||||
"name": user.name,
|
"name": user.name,
|
||||||
"system_generated": user.system_generated,
|
"system_generated": user.system_generated,
|
||||||
|
"local_only": user.local_only,
|
||||||
}
|
}
|
||||||
for user in self._users.values()
|
for user in self._users.values()
|
||||||
]
|
]
|
||||||
|
@ -100,7 +100,7 @@ class NotifyAuthModule(MultiFactorAuthModule):
|
|||||||
super().__init__(hass, config)
|
super().__init__(hass, config)
|
||||||
self._user_settings: _UsersDict | None = None
|
self._user_settings: _UsersDict | None = None
|
||||||
self._user_store = hass.helpers.storage.Store(
|
self._user_store = hass.helpers.storage.Store(
|
||||||
STORAGE_VERSION, STORAGE_KEY, private=True
|
STORAGE_VERSION, STORAGE_KEY, private=True, atomic_writes=True
|
||||||
)
|
)
|
||||||
self._include = config.get(CONF_INCLUDE, [])
|
self._include = config.get(CONF_INCLUDE, [])
|
||||||
self._exclude = config.get(CONF_EXCLUDE, [])
|
self._exclude = config.get(CONF_EXCLUDE, [])
|
||||||
|
@ -77,7 +77,7 @@ class TotpAuthModule(MultiFactorAuthModule):
|
|||||||
super().__init__(hass, config)
|
super().__init__(hass, config)
|
||||||
self._users: dict[str, str] | None = None
|
self._users: dict[str, str] | None = None
|
||||||
self._user_store = hass.helpers.storage.Store(
|
self._user_store = hass.helpers.storage.Store(
|
||||||
STORAGE_VERSION, STORAGE_KEY, private=True
|
STORAGE_VERSION, STORAGE_KEY, private=True, atomic_writes=True
|
||||||
)
|
)
|
||||||
self._init_lock = asyncio.Lock()
|
self._init_lock = asyncio.Lock()
|
||||||
|
|
||||||
|
@ -39,6 +39,7 @@ class User:
|
|||||||
is_owner: bool = attr.ib(default=False)
|
is_owner: bool = attr.ib(default=False)
|
||||||
is_active: bool = attr.ib(default=False)
|
is_active: bool = attr.ib(default=False)
|
||||||
system_generated: bool = attr.ib(default=False)
|
system_generated: bool = attr.ib(default=False)
|
||||||
|
local_only: bool = attr.ib(default=False)
|
||||||
|
|
||||||
groups: list[Group] = attr.ib(factory=list, eq=False, order=False)
|
groups: list[Group] = attr.ib(factory=list, eq=False, order=False)
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ class Data:
|
|||||||
"""Initialize the user data store."""
|
"""Initialize the user data store."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self._store = hass.helpers.storage.Store(
|
self._store = hass.helpers.storage.Store(
|
||||||
STORAGE_VERSION, STORAGE_KEY, private=True
|
STORAGE_VERSION, STORAGE_KEY, private=True, atomic_writes=True
|
||||||
)
|
)
|
||||||
self._data: dict[str, Any] | None = None
|
self._data: dict[str, Any] | None = None
|
||||||
# Legacy mode will allow usernames to start/end with whitespace
|
# Legacy mode will allow usernames to start/end with whitespace
|
||||||
|
@ -102,7 +102,7 @@ class ExampleLoginFlow(LoginFlow):
|
|||||||
self, user_input: dict[str, str] | None = None
|
self, user_input: dict[str, str] | None = None
|
||||||
) -> FlowResult:
|
) -> FlowResult:
|
||||||
"""Handle the step of the form."""
|
"""Handle the step of the form."""
|
||||||
errors = {}
|
errors = None
|
||||||
|
|
||||||
if user_input is not None:
|
if user_input is not None:
|
||||||
try:
|
try:
|
||||||
@ -110,7 +110,7 @@ class ExampleLoginFlow(LoginFlow):
|
|||||||
user_input["username"], user_input["password"]
|
user_input["username"], user_input["password"]
|
||||||
)
|
)
|
||||||
except InvalidAuthError:
|
except InvalidAuthError:
|
||||||
errors["base"] = "invalid_auth"
|
errors = {"base": "invalid_auth"}
|
||||||
|
|
||||||
if not errors:
|
if not errors:
|
||||||
user_input.pop("password")
|
user_input.pop("password")
|
||||||
|
@ -194,6 +194,12 @@ class TrustedNetworksAuthProvider(AuthProvider):
|
|||||||
if any(ip_addr in trusted_proxy for trusted_proxy in self.trusted_proxies):
|
if any(ip_addr in trusted_proxy for trusted_proxy in self.trusted_proxies):
|
||||||
raise InvalidAuthError("Can't allow access from a proxy server")
|
raise InvalidAuthError("Can't allow access from a proxy server")
|
||||||
|
|
||||||
|
if "cloud" in self.hass.config.components:
|
||||||
|
from hass_nabucasa import remote # pylint: disable=import-outside-toplevel
|
||||||
|
|
||||||
|
if remote.is_cloud_request.get():
|
||||||
|
raise InvalidAuthError("Can't allow access from Home Assistant Cloud")
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def async_validate_refresh_token(
|
def async_validate_refresh_token(
|
||||||
self, refresh_token: RefreshToken, remote_ip: str | None = None
|
self, refresh_token: RefreshToken, remote_ip: str | None = None
|
||||||
|
1
homeassistant/backports/__init__.py
Normal file
1
homeassistant/backports/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""Backports from newer Python versions."""
|
33
homeassistant/backports/enum.py
Normal file
33
homeassistant/backports/enum.py
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
"""Enum backports from standard lib."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
from typing import Any, TypeVar
|
||||||
|
|
||||||
|
T = TypeVar("T", bound="StrEnum")
|
||||||
|
|
||||||
|
|
||||||
|
class StrEnum(str, Enum):
|
||||||
|
"""Partial backport of Python 3.11's StrEnum for our basic use cases."""
|
||||||
|
|
||||||
|
def __new__(cls: type[T], value: str, *args: Any, **kwargs: Any) -> T:
|
||||||
|
"""Create a new StrEnum instance."""
|
||||||
|
if not isinstance(value, str):
|
||||||
|
raise TypeError(f"{value!r} is not a string")
|
||||||
|
return super().__new__(cls, value, *args, **kwargs) # type: ignore[call-overload,no-any-return]
|
||||||
|
|
||||||
|
def __str__(self) -> str:
|
||||||
|
"""Return self.value."""
|
||||||
|
return str(self.value)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _generate_next_value_( # pylint: disable=arguments-differ # https://github.com/PyCQA/pylint/issues/5371
|
||||||
|
name: str, start: int, count: int, last_values: list[Any]
|
||||||
|
) -> Any:
|
||||||
|
"""
|
||||||
|
Make `auto()` explicitly unsupported.
|
||||||
|
|
||||||
|
We may revisit this when it's very clear that Python 3.11's
|
||||||
|
`StrEnum.auto()` behavior will no longer change.
|
||||||
|
"""
|
||||||
|
raise TypeError("auto() is not supported by this implementation")
|
@ -252,8 +252,7 @@ async def async_from_config_dict(
|
|||||||
f"{'.'.join(str(x) for x in sys.version_info[:3])} is deprecated and will "
|
f"{'.'.join(str(x) for x in sys.version_info[:3])} is deprecated and will "
|
||||||
f"be removed in Home Assistant {REQUIRED_NEXT_PYTHON_HA_RELEASE}. "
|
f"be removed in Home Assistant {REQUIRED_NEXT_PYTHON_HA_RELEASE}. "
|
||||||
"Please upgrade Python to "
|
"Please upgrade Python to "
|
||||||
f"{'.'.join(str(x) for x in REQUIRED_NEXT_PYTHON_VER)} or "
|
f"{'.'.join(str(x) for x in REQUIRED_NEXT_PYTHON_VER[:2])}."
|
||||||
"higher."
|
|
||||||
)
|
)
|
||||||
_LOGGER.warning(msg)
|
_LOGGER.warning(msg)
|
||||||
hass.components.persistent_notification.async_create(
|
hass.components.persistent_notification.async_create(
|
||||||
|
@ -16,6 +16,7 @@ from homeassistant.const import (
|
|||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
EVENT_HOMEASSISTANT_STOP,
|
EVENT_HOMEASSISTANT_STOP,
|
||||||
|
Platform,
|
||||||
)
|
)
|
||||||
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
@ -53,14 +54,14 @@ CAPTURE_IMAGE_SCHEMA = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids})
|
|||||||
AUTOMATION_SCHEMA = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids})
|
AUTOMATION_SCHEMA = vol.Schema({ATTR_ENTITY_ID: cv.entity_ids})
|
||||||
|
|
||||||
PLATFORMS = [
|
PLATFORMS = [
|
||||||
"alarm_control_panel",
|
Platform.ALARM_CONTROL_PANEL,
|
||||||
"binary_sensor",
|
Platform.BINARY_SENSOR,
|
||||||
"lock",
|
Platform.LOCK,
|
||||||
"switch",
|
Platform.SWITCH,
|
||||||
"cover",
|
Platform.COVER,
|
||||||
"camera",
|
Platform.CAMERA,
|
||||||
"light",
|
Platform.LIGHT,
|
||||||
"sensor",
|
Platform.SENSOR,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
35
homeassistant/components/abode/translations/ja.json
Normal file
35
homeassistant/components/abode/translations/ja.json
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"reauth_successful": "\u518d\u8a8d\u8a3c\u306b\u6210\u529f\u3057\u307e\u3057\u305f",
|
||||||
|
"single_instance_allowed": "\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u5358\u4e00\u306e\u8a2d\u5b9a\u3057\u304b\u3067\u304d\u307e\u305b\u3093\u3002"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f",
|
||||||
|
"invalid_auth": "\u7121\u52b9\u306a\u8a8d\u8a3c",
|
||||||
|
"invalid_mfa_code": "\u7121\u52b9\u306aMFA\u30b3\u30fc\u30c9"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"mfa": {
|
||||||
|
"data": {
|
||||||
|
"mfa_code": "MFA\u30b3\u30fc\u30c9(6\u6841)"
|
||||||
|
},
|
||||||
|
"title": "Abode\u306eMFA\u30b3\u30fc\u30c9\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044"
|
||||||
|
},
|
||||||
|
"reauth_confirm": {
|
||||||
|
"data": {
|
||||||
|
"password": "\u30d1\u30b9\u30ef\u30fc\u30c9",
|
||||||
|
"username": "E\u30e1\u30fc\u30eb"
|
||||||
|
},
|
||||||
|
"title": "Abode\u306e\u30ed\u30b0\u30a4\u30f3\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"password": "\u30d1\u30b9\u30ef\u30fc\u30c9",
|
||||||
|
"username": "E\u30e1\u30fc\u30eb"
|
||||||
|
},
|
||||||
|
"title": "Abode\u306e\u30ed\u30b0\u30a4\u30f3\u60c5\u5831\u3092\u5165\u529b\u3057\u3066\u304f\u3060\u3055\u3044"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -27,7 +27,8 @@
|
|||||||
"data": {
|
"data": {
|
||||||
"password": "Parola",
|
"password": "Parola",
|
||||||
"username": "E-posta"
|
"username": "E-posta"
|
||||||
}
|
},
|
||||||
|
"title": "Abode giri\u015f bilgilerinizi doldurun"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ from aiohttp.client_exceptions import ClientConnectorError
|
|||||||
from async_timeout import timeout
|
from async_timeout import timeout
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_API_KEY
|
from homeassistant.const import CONF_API_KEY, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
@ -20,7 +20,7 @@ from .const import ATTR_FORECAST, CONF_FORECAST, DOMAIN
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
PLATFORMS = ["sensor", "weather"]
|
PLATFORMS = [Platform.SENSOR, Platform.WEATHER]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
@ -3,7 +3,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
from typing import Final
|
from typing import Final
|
||||||
|
|
||||||
from homeassistant.components.sensor import STATE_CLASS_MEASUREMENT
|
from homeassistant.components.sensor import SensorStateClass
|
||||||
from homeassistant.components.weather import (
|
from homeassistant.components.weather import (
|
||||||
ATTR_CONDITION_CLEAR_NIGHT,
|
ATTR_CONDITION_CLEAR_NIGHT,
|
||||||
ATTR_CONDITION_CLOUDY,
|
ATTR_CONDITION_CLOUDY,
|
||||||
@ -220,7 +220,7 @@ SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
|
|||||||
unit_metric=TEMP_CELSIUS,
|
unit_metric=TEMP_CELSIUS,
|
||||||
unit_imperial=TEMP_FAHRENHEIT,
|
unit_imperial=TEMP_FAHRENHEIT,
|
||||||
entity_registry_enabled_default=False,
|
entity_registry_enabled_default=False,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
AccuWeatherSensorDescription(
|
AccuWeatherSensorDescription(
|
||||||
key="Ceiling",
|
key="Ceiling",
|
||||||
@ -228,7 +228,7 @@ SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
|
|||||||
name="Cloud Ceiling",
|
name="Cloud Ceiling",
|
||||||
unit_metric=LENGTH_METERS,
|
unit_metric=LENGTH_METERS,
|
||||||
unit_imperial=LENGTH_FEET,
|
unit_imperial=LENGTH_FEET,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
AccuWeatherSensorDescription(
|
AccuWeatherSensorDescription(
|
||||||
key="CloudCover",
|
key="CloudCover",
|
||||||
@ -237,7 +237,7 @@ SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
|
|||||||
unit_metric=PERCENTAGE,
|
unit_metric=PERCENTAGE,
|
||||||
unit_imperial=PERCENTAGE,
|
unit_imperial=PERCENTAGE,
|
||||||
entity_registry_enabled_default=False,
|
entity_registry_enabled_default=False,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
AccuWeatherSensorDescription(
|
AccuWeatherSensorDescription(
|
||||||
key="DewPoint",
|
key="DewPoint",
|
||||||
@ -246,7 +246,7 @@ SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
|
|||||||
unit_metric=TEMP_CELSIUS,
|
unit_metric=TEMP_CELSIUS,
|
||||||
unit_imperial=TEMP_FAHRENHEIT,
|
unit_imperial=TEMP_FAHRENHEIT,
|
||||||
entity_registry_enabled_default=False,
|
entity_registry_enabled_default=False,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
AccuWeatherSensorDescription(
|
AccuWeatherSensorDescription(
|
||||||
key="RealFeelTemperature",
|
key="RealFeelTemperature",
|
||||||
@ -254,7 +254,7 @@ SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
|
|||||||
name="RealFeel Temperature",
|
name="RealFeel Temperature",
|
||||||
unit_metric=TEMP_CELSIUS,
|
unit_metric=TEMP_CELSIUS,
|
||||||
unit_imperial=TEMP_FAHRENHEIT,
|
unit_imperial=TEMP_FAHRENHEIT,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
AccuWeatherSensorDescription(
|
AccuWeatherSensorDescription(
|
||||||
key="RealFeelTemperatureShade",
|
key="RealFeelTemperatureShade",
|
||||||
@ -263,7 +263,7 @@ SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
|
|||||||
unit_metric=TEMP_CELSIUS,
|
unit_metric=TEMP_CELSIUS,
|
||||||
unit_imperial=TEMP_FAHRENHEIT,
|
unit_imperial=TEMP_FAHRENHEIT,
|
||||||
entity_registry_enabled_default=False,
|
entity_registry_enabled_default=False,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
AccuWeatherSensorDescription(
|
AccuWeatherSensorDescription(
|
||||||
key="Precipitation",
|
key="Precipitation",
|
||||||
@ -271,7 +271,7 @@ SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
|
|||||||
name="Precipitation",
|
name="Precipitation",
|
||||||
unit_metric=LENGTH_MILLIMETERS,
|
unit_metric=LENGTH_MILLIMETERS,
|
||||||
unit_imperial=LENGTH_INCHES,
|
unit_imperial=LENGTH_INCHES,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
AccuWeatherSensorDescription(
|
AccuWeatherSensorDescription(
|
||||||
key="PressureTendency",
|
key="PressureTendency",
|
||||||
@ -287,7 +287,7 @@ SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
|
|||||||
name="UV Index",
|
name="UV Index",
|
||||||
unit_metric=UV_INDEX,
|
unit_metric=UV_INDEX,
|
||||||
unit_imperial=UV_INDEX,
|
unit_imperial=UV_INDEX,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
AccuWeatherSensorDescription(
|
AccuWeatherSensorDescription(
|
||||||
key="WetBulbTemperature",
|
key="WetBulbTemperature",
|
||||||
@ -296,7 +296,7 @@ SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
|
|||||||
unit_metric=TEMP_CELSIUS,
|
unit_metric=TEMP_CELSIUS,
|
||||||
unit_imperial=TEMP_FAHRENHEIT,
|
unit_imperial=TEMP_FAHRENHEIT,
|
||||||
entity_registry_enabled_default=False,
|
entity_registry_enabled_default=False,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
AccuWeatherSensorDescription(
|
AccuWeatherSensorDescription(
|
||||||
key="WindChillTemperature",
|
key="WindChillTemperature",
|
||||||
@ -305,7 +305,7 @@ SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
|
|||||||
unit_metric=TEMP_CELSIUS,
|
unit_metric=TEMP_CELSIUS,
|
||||||
unit_imperial=TEMP_FAHRENHEIT,
|
unit_imperial=TEMP_FAHRENHEIT,
|
||||||
entity_registry_enabled_default=False,
|
entity_registry_enabled_default=False,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
AccuWeatherSensorDescription(
|
AccuWeatherSensorDescription(
|
||||||
key="Wind",
|
key="Wind",
|
||||||
@ -313,7 +313,7 @@ SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
|
|||||||
name="Wind",
|
name="Wind",
|
||||||
unit_metric=SPEED_KILOMETERS_PER_HOUR,
|
unit_metric=SPEED_KILOMETERS_PER_HOUR,
|
||||||
unit_imperial=SPEED_MILES_PER_HOUR,
|
unit_imperial=SPEED_MILES_PER_HOUR,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
AccuWeatherSensorDescription(
|
AccuWeatherSensorDescription(
|
||||||
key="WindGust",
|
key="WindGust",
|
||||||
@ -322,6 +322,6 @@ SENSOR_TYPES: Final[tuple[AccuWeatherSensorDescription, ...]] = (
|
|||||||
unit_metric=SPEED_KILOMETERS_PER_HOUR,
|
unit_metric=SPEED_KILOMETERS_PER_HOUR,
|
||||||
unit_imperial=SPEED_MILES_PER_HOUR,
|
unit_imperial=SPEED_MILES_PER_HOUR,
|
||||||
entity_registry_enabled_default=False,
|
entity_registry_enabled_default=False,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -7,6 +7,7 @@ from homeassistant.components.sensor import SensorEntity
|
|||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_NAME, DEVICE_CLASS_TEMPERATURE
|
from homeassistant.const import CONF_NAME, DEVICE_CLASS_TEMPERATURE
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers.device_registry import DeviceEntryType
|
||||||
from homeassistant.helpers.entity import DeviceInfo
|
from homeassistant.helpers.entity import DeviceInfo
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import StateType
|
from homeassistant.helpers.typing import StateType
|
||||||
@ -95,7 +96,7 @@ class AccuWeatherSensor(CoordinatorEntity, SensorEntity):
|
|||||||
self._unit_system = API_IMPERIAL
|
self._unit_system = API_IMPERIAL
|
||||||
self._attr_native_unit_of_measurement = description.unit_imperial
|
self._attr_native_unit_of_measurement = description.unit_imperial
|
||||||
self._attr_device_info = DeviceInfo(
|
self._attr_device_info = DeviceInfo(
|
||||||
entry_type="service",
|
entry_type=DeviceEntryType.SERVICE,
|
||||||
identifiers={(DOMAIN, coordinator.location_key)},
|
identifiers={(DOMAIN, coordinator.location_key)},
|
||||||
manufacturer=MANUFACTURER,
|
manufacturer=MANUFACTURER,
|
||||||
name=NAME,
|
name=NAME,
|
||||||
|
@ -1,7 +1,22 @@
|
|||||||
{
|
{
|
||||||
"config": {
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"single_instance_allowed": "\u0412\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e. \u0412\u044a\u0437\u043c\u043e\u0436\u043d\u0430 \u0435 \u0441\u0430\u043c\u043e \u0435\u0434\u043d\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044f."
|
||||||
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0445 \u043f\u0440\u0438 \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435"
|
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0445 \u043f\u0440\u0438 \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
|
||||||
|
"invalid_api_key": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d API \u043a\u043b\u044e\u0447"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"api_key": "API \u043a\u043b\u044e\u0447",
|
||||||
|
"latitude": "\u0413\u0435\u043e\u0433\u0440\u0430\u0444\u0441\u043a\u0430 \u0448\u0438\u0440\u0438\u043d\u0430",
|
||||||
|
"longitude": "\u0413\u0435\u043e\u0433\u0440\u0430\u0444\u0441\u043a\u0430 \u0434\u044a\u043b\u0436\u0438\u043d\u0430",
|
||||||
|
"name": "\u0418\u043c\u0435"
|
||||||
|
},
|
||||||
|
"title": "AccuWeather"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
41
homeassistant/components/accuweather/translations/ja.json
Normal file
41
homeassistant/components/accuweather/translations/ja.json
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"single_instance_allowed": "\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u5358\u4e00\u306e\u8a2d\u5b9a\u3057\u304b\u3067\u304d\u307e\u305b\u3093\u3002"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f",
|
||||||
|
"invalid_api_key": "\u7121\u52b9\u306aAPI\u30ad\u30fc",
|
||||||
|
"requests_exceeded": "Accuweather API\u3078\u306e\u30ea\u30af\u30a8\u30b9\u30c8\u6570\u304c\u8a31\u53ef\u3055\u308c\u305f\u6570\u3092\u8d85\u3048\u307e\u3057\u305f\u3002\u6642\u9593\u3092\u7f6e\u304f\u304b\u3001API\u30ad\u30fc\u3092\u5909\u66f4\u3059\u308b\u5fc5\u8981\u304c\u3042\u308a\u307e\u3059\u3002"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"api_key": "API\u30ad\u30fc",
|
||||||
|
"latitude": "\u7def\u5ea6",
|
||||||
|
"longitude": "\u7d4c\u5ea6",
|
||||||
|
"name": "\u540d\u524d"
|
||||||
|
},
|
||||||
|
"description": "\u8a2d\u5b9a\u306b\u3064\u3044\u3066\u30d8\u30eb\u30d7\u304c\u5fc5\u8981\u306a\u5834\u5408\u306f\u3001https://www.home-assistant.io/integrations/accuweather/ \u306b\u30a2\u30af\u30bb\u30b9\u3057\u3066\u304f\u3060\u3055\u3044\n\n\u4e00\u90e8\u306e\u30bb\u30f3\u30b5\u30fc\u306f\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u306f\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002\u30a4\u30f3\u30c6\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u3067\u306e\u8a2d\u5b9a\u5f8c\u306b\u3001\u30a8\u30f3\u30c6\u30a3\u30c6\u30a3\u30ec\u30b8\u30b9\u30c8\u30ea\u3067\u6709\u52b9\u306b\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002\n\u5929\u6c17\u4e88\u5831\u306f\u30c7\u30d5\u30a9\u30eb\u30c8\u3067\u306f\u6709\u52b9\u306b\u306a\u3063\u3066\u3044\u307e\u305b\u3093\u3002\u30a4\u30f3\u30c6\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u306e\u30aa\u30d7\u30b7\u30e7\u30f3\u3067\u6709\u52b9\u306b\u3059\u308b\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002",
|
||||||
|
"title": "AccuWeather"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"forecast": "\u5929\u6c17\u4e88\u5831"
|
||||||
|
},
|
||||||
|
"description": "\u5236\u9650\u306b\u3088\u308a\u7121\u6599\u30d0\u30fc\u30b8\u30e7\u30f3\u306eAccuWeather API\u30ad\u30fc\u3067\u306f\u3001\u5929\u6c17\u4e88\u5831\u3092\u6709\u52b9\u306b\u3057\u3066\u3082\u30c7\u30fc\u30bf\u306e\u66f4\u65b0\u306f40\u5206\u3067\u306f\u306a\u304f80\u5206\u3054\u3068\u3067\u3059\u3002",
|
||||||
|
"title": "AccuWeather\u306e\u30aa\u30d7\u30b7\u30e7\u30f3"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"system_health": {
|
||||||
|
"info": {
|
||||||
|
"can_reach_server": "AccuWeather\u30b5\u30fc\u30d0\u30fc\u306b\u5230\u9054",
|
||||||
|
"remaining_requests": "\u6b8b\u308a\u306e\u8a31\u53ef\u3055\u308c\u305f\u30ea\u30af\u30a8\u30b9\u30c8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"state": {
|
||||||
|
"accuweather__pressure_tendency": {
|
||||||
|
"falling": "\u4e0b\u964d",
|
||||||
|
"rising": "\u4e0a\u6607",
|
||||||
|
"steady": "\u5b89\u5b9a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"state": {
|
||||||
|
"accuweather__pressure_tendency": {
|
||||||
|
"falling": "D\u00fc\u015f\u00fcyor",
|
||||||
|
"rising": "Y\u00fckseliyor",
|
||||||
|
"steady": "Sabit"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,7 +5,8 @@
|
|||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"cannot_connect": "Ba\u011flanma hatas\u0131",
|
"cannot_connect": "Ba\u011flanma hatas\u0131",
|
||||||
"invalid_api_key": "Ge\u00e7ersiz API anahtar\u0131"
|
"invalid_api_key": "Ge\u00e7ersiz API anahtar\u0131",
|
||||||
|
"requests_exceeded": "Accuweather API i\u00e7in izin verilen istek say\u0131s\u0131 a\u015f\u0131ld\u0131. API Anahtar\u0131n\u0131 beklemeniz veya de\u011fi\u015ftirmeniz gerekir."
|
||||||
},
|
},
|
||||||
"step": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
@ -15,6 +16,7 @@
|
|||||||
"longitude": "Boylam",
|
"longitude": "Boylam",
|
||||||
"name": "Ad"
|
"name": "Ad"
|
||||||
},
|
},
|
||||||
|
"description": "Yap\u0131land\u0131rmayla ilgili yard\u0131ma ihtiyac\u0131n\u0131z varsa buraya bak\u0131n: https://www.home-assistant.io/integrations/accuweather/ \n\n Baz\u0131 sens\u00f6rler varsay\u0131lan olarak etkin de\u011fildir. Bunlar\u0131, entegrasyon yap\u0131land\u0131rmas\u0131ndan sonra varl\u0131k kay\u0131t defterinde etkinle\u015ftirebilirsiniz.\n Hava tahmini varsay\u0131lan olarak etkin de\u011fildir. Entegrasyon se\u00e7eneklerinde etkinle\u015ftirebilirsiniz.",
|
||||||
"title": "AccuWeather"
|
"title": "AccuWeather"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -25,6 +27,7 @@
|
|||||||
"data": {
|
"data": {
|
||||||
"forecast": "Hava Durumu tahmini"
|
"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.",
|
||||||
"title": "AccuWeather Se\u00e7enekleri"
|
"title": "AccuWeather Se\u00e7enekleri"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ from homeassistant.components.weather import (
|
|||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_NAME, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
from homeassistant.const import CONF_NAME, TEMP_CELSIUS, TEMP_FAHRENHEIT
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.device_registry import DeviceEntryType
|
||||||
from homeassistant.helpers.entity import DeviceInfo
|
from homeassistant.helpers.entity import DeviceInfo
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
from homeassistant.helpers.update_coordinator import CoordinatorEntity
|
||||||
@ -68,10 +69,16 @@ class AccuWeatherEntity(CoordinatorEntity, WeatherEntity):
|
|||||||
)
|
)
|
||||||
self._attr_attribution = ATTRIBUTION
|
self._attr_attribution = ATTRIBUTION
|
||||||
self._attr_device_info = DeviceInfo(
|
self._attr_device_info = DeviceInfo(
|
||||||
entry_type="service",
|
entry_type=DeviceEntryType.SERVICE,
|
||||||
identifiers={(DOMAIN, coordinator.location_key)},
|
identifiers={(DOMAIN, coordinator.location_key)},
|
||||||
manufacturer=MANUFACTURER,
|
manufacturer=MANUFACTURER,
|
||||||
name=NAME,
|
name=NAME,
|
||||||
|
# You don't need to provide specific details for the URL,
|
||||||
|
# so passing in _ characters is fine if the location key
|
||||||
|
# is correct
|
||||||
|
configuration_url="http://accuweather.com/en/"
|
||||||
|
f"_/_/{coordinator.location_key}/"
|
||||||
|
f"weather-forecast/{coordinator.location_key}/",
|
||||||
)
|
)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -111,8 +111,7 @@ class AcerSwitch(SwitchEntity):
|
|||||||
"""Write msg, obtain answer and format output."""
|
"""Write msg, obtain answer and format output."""
|
||||||
# answers are formatted as ***\answer\r***
|
# answers are formatted as ***\answer\r***
|
||||||
awns = self._write_read(msg)
|
awns = self._write_read(msg)
|
||||||
match = re.search(r"\r(.+)\r", awns)
|
if match := re.search(r"\r(.+)\r", awns):
|
||||||
if match:
|
|
||||||
return match.group(1)
|
return match.group(1)
|
||||||
return STATE_UNKNOWN
|
return STATE_UNKNOWN
|
||||||
|
|
||||||
|
@ -1,13 +1,14 @@
|
|||||||
"""The Rollease Acmeda Automate integration."""
|
"""The Rollease Acmeda Automate integration."""
|
||||||
|
|
||||||
from homeassistant import config_entries, core
|
from homeassistant import config_entries, core
|
||||||
|
from homeassistant.const import Platform
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
from .hub import PulseHub
|
from .hub import PulseHub
|
||||||
|
|
||||||
CONF_HUBS = "hubs"
|
CONF_HUBS = "hubs"
|
||||||
|
|
||||||
PLATFORMS = ["cover", "sensor"]
|
PLATFORMS = [Platform.COVER, Platform.SENSOR]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(
|
async def async_setup_entry(
|
||||||
|
@ -9,6 +9,7 @@ import async_timeout
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import config_entries
|
from homeassistant import config_entries
|
||||||
|
from homeassistant.const import CONF_HOST, CONF_ID
|
||||||
|
|
||||||
from .const import DOMAIN
|
from .const import DOMAIN
|
||||||
|
|
||||||
@ -27,9 +28,9 @@ class AcmedaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
if (
|
if (
|
||||||
user_input is not None
|
user_input is not None
|
||||||
and self.discovered_hubs is not None
|
and self.discovered_hubs is not None
|
||||||
and user_input["id"] in self.discovered_hubs
|
and user_input[CONF_ID] in self.discovered_hubs
|
||||||
):
|
):
|
||||||
return await self.async_create(self.discovered_hubs[user_input["id"]])
|
return await self.async_create(self.discovered_hubs[user_input[CONF_ID]])
|
||||||
|
|
||||||
# Already configured hosts
|
# Already configured hosts
|
||||||
already_configured = {
|
already_configured = {
|
||||||
@ -55,7 +56,7 @@ class AcmedaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
step_id="user",
|
step_id="user",
|
||||||
data_schema=vol.Schema(
|
data_schema=vol.Schema(
|
||||||
{
|
{
|
||||||
vol.Required("id"): vol.In(
|
vol.Required(CONF_ID): vol.In(
|
||||||
{hub.id: f"{hub.id} {hub.host}" for hub in hubs}
|
{hub.id: f"{hub.id} {hub.host}" for hub in hubs}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -65,4 +66,4 @@ class AcmedaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
async def async_create(self, hub):
|
async def async_create(self, hub):
|
||||||
"""Create the Acmeda Hub entry."""
|
"""Create the Acmeda Hub entry."""
|
||||||
await self.async_set_unique_id(hub.id, raise_on_progress=False)
|
await self.async_set_unique_id(hub.id, raise_on_progress=False)
|
||||||
return self.async_create_entry(title=hub.id, data={"host": hub.host})
|
return self.async_create_entry(title=hub.id, data={CONF_HOST: hub.host})
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "Rollease Acmeda Automate",
|
"name": "Rollease Acmeda Automate",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/acmeda",
|
"documentation": "https://www.home-assistant.io/integrations/acmeda",
|
||||||
"requirements": ["aiopulse==0.4.2"],
|
"requirements": ["aiopulse==0.4.3"],
|
||||||
"codeowners": ["@atmurray"],
|
"codeowners": ["@atmurray"],
|
||||||
"iot_class": "local_push"
|
"iot_class": "local_push"
|
||||||
}
|
}
|
||||||
|
15
homeassistant/components/acmeda/translations/ja.json
Normal file
15
homeassistant/components/acmeda/translations/ja.json
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"no_devices_found": "\u30cd\u30c3\u30c8\u30ef\u30fc\u30af\u4e0a\u306b\u30c7\u30d0\u30a4\u30b9\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"id": "\u30db\u30b9\u30c8ID"
|
||||||
|
},
|
||||||
|
"title": "\u8ffd\u52a0\u3059\u308b\u30cf\u30d6\u306e\u9078\u629e"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,10 +1,14 @@
|
|||||||
{
|
{
|
||||||
"config": {
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"no_devices_found": "A\u011fda cihaz bulunamad\u0131"
|
||||||
|
},
|
||||||
"step": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
"id": "Ana bilgisayar kimli\u011fi"
|
"id": "Ana bilgisayar kimli\u011fi"
|
||||||
}
|
},
|
||||||
|
"title": "Eklemek i\u00e7in bir merkez se\u00e7in"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -71,8 +71,7 @@ class ActiontecDeviceScanner(DeviceScanner):
|
|||||||
if not self.success_init:
|
if not self.success_init:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
actiontec_data = self.get_actiontec_data()
|
if (actiontec_data := self.get_actiontec_data()) is None:
|
||||||
if actiontec_data is None:
|
|
||||||
return False
|
return False
|
||||||
self.last_results = [
|
self.last_results = [
|
||||||
device for device in actiontec_data if device.timevalid > -60
|
device for device in actiontec_data if device.timevalid > -60
|
||||||
|
@ -2,9 +2,10 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
|
||||||
PLATFORMS = ["climate"]
|
PLATFORMS = [Platform.CLIMATE]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/adax",
|
"documentation": "https://www.home-assistant.io/integrations/adax",
|
||||||
"requirements": [
|
"requirements": [
|
||||||
"adax==0.1.1"
|
"adax==0.2.0"
|
||||||
],
|
],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
"@danielhiversen"
|
"@danielhiversen"
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"already_configured": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u0442\u043e \u0432\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e"
|
"already_configured": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u0442\u043e \u0432\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0445 \u043f\u0440\u0438 \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
|
"cannot_connect": "\u041d\u0435\u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0441\u0432\u044a\u0440\u0437\u0432\u0430\u043d\u0435",
|
||||||
"invalid_auth": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435"
|
"invalid_auth": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u043d\u043e \u0443\u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u044f\u0432\u0430\u043d\u0435"
|
||||||
},
|
},
|
||||||
"step": {
|
"step": {
|
||||||
|
20
homeassistant/components/adax/translations/ja.json
Normal file
20
homeassistant/components/adax/translations/ja.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "\u30c7\u30d0\u30a4\u30b9\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f",
|
||||||
|
"invalid_auth": "\u7121\u52b9\u306a\u8a8d\u8a3c"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"account_id": "\u30a2\u30ab\u30a6\u30f3\u30c8ID",
|
||||||
|
"host": "\u30db\u30b9\u30c8",
|
||||||
|
"password": "\u30d1\u30b9\u30ef\u30fc\u30c9"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
20
homeassistant/components/adax/translations/tr.json
Normal file
20
homeassistant/components/adax/translations/tr.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"account_id": "Hesap Kimli\u011fi",
|
||||||
|
"host": "Ana bilgisayar",
|
||||||
|
"password": "Parola"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ import logging
|
|||||||
from adguardhome import AdGuardHome, AdGuardHomeConnectionError, AdGuardHomeError
|
from adguardhome import AdGuardHome, AdGuardHomeConnectionError, AdGuardHomeError
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import SOURCE_HASSIO, ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_HOST,
|
CONF_HOST,
|
||||||
CONF_NAME,
|
CONF_NAME,
|
||||||
@ -16,11 +16,13 @@ from homeassistant.const import (
|
|||||||
CONF_URL,
|
CONF_URL,
|
||||||
CONF_USERNAME,
|
CONF_USERNAME,
|
||||||
CONF_VERIFY_SSL,
|
CONF_VERIFY_SSL,
|
||||||
|
Platform,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
from homeassistant.helpers import config_validation as cv
|
from homeassistant.helpers import config_validation as cv
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
|
from homeassistant.helpers.device_registry import DeviceEntryType
|
||||||
from homeassistant.helpers.entity import DeviceInfo, Entity
|
from homeassistant.helpers.entity import DeviceInfo, Entity
|
||||||
|
|
||||||
from .const import (
|
from .const import (
|
||||||
@ -45,7 +47,7 @@ SERVICE_REFRESH_SCHEMA = vol.Schema(
|
|||||||
{vol.Optional(CONF_FORCE, default=False): cv.boolean}
|
{vol.Optional(CONF_FORCE, default=False): cv.boolean}
|
||||||
)
|
)
|
||||||
|
|
||||||
PLATFORMS = ["sensor", "switch"]
|
PLATFORMS = [Platform.SENSOR, Platform.SWITCH]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
@ -196,8 +198,16 @@ class AdGuardHomeDeviceEntity(AdGuardHomeEntity):
|
|||||||
@property
|
@property
|
||||||
def device_info(self) -> DeviceInfo:
|
def device_info(self) -> DeviceInfo:
|
||||||
"""Return device information about this AdGuard Home instance."""
|
"""Return device information about this AdGuard Home instance."""
|
||||||
|
if self._entry.source == SOURCE_HASSIO:
|
||||||
|
config_url = "homeassistant://hassio/ingress/a0d7b954_adguard"
|
||||||
|
else:
|
||||||
|
if self.adguard.tls:
|
||||||
|
config_url = f"https://{self.adguard.host}:{self.adguard.port}"
|
||||||
|
else:
|
||||||
|
config_url = f"http://{self.adguard.host}:{self.adguard.port}"
|
||||||
|
|
||||||
return DeviceInfo(
|
return DeviceInfo(
|
||||||
entry_type="service",
|
entry_type=DeviceEntryType.SERVICE,
|
||||||
identifiers={
|
identifiers={
|
||||||
(DOMAIN, self.adguard.host, self.adguard.port, self.adguard.base_path) # type: ignore
|
(DOMAIN, self.adguard.host, self.adguard.port, self.adguard.base_path) # type: ignore
|
||||||
},
|
},
|
||||||
@ -206,4 +216,5 @@ class AdGuardHomeDeviceEntity(AdGuardHomeEntity):
|
|||||||
sw_version=self.hass.data[DOMAIN][self._entry.entry_id].get(
|
sw_version=self.hass.data[DOMAIN][self._entry.entry_id].get(
|
||||||
DATA_ADGUARD_VERSION
|
DATA_ADGUARD_VERSION
|
||||||
),
|
),
|
||||||
|
configuration_url=config_url,
|
||||||
)
|
)
|
||||||
|
@ -6,6 +6,7 @@ from typing import Any
|
|||||||
from adguardhome import AdGuardHome, AdGuardHomeConnectionError
|
from adguardhome import AdGuardHome, AdGuardHomeConnectionError
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
|
from homeassistant.components.hassio import HassioServiceInfo
|
||||||
from homeassistant.config_entries import ConfigFlow
|
from homeassistant.config_entries import ConfigFlow
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_HOST,
|
CONF_HOST,
|
||||||
@ -104,14 +105,14 @@ class AdGuardHomeFlowHandler(ConfigFlow, domain=DOMAIN):
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
async def async_step_hassio(self, discovery_info: dict[str, Any]) -> FlowResult:
|
async def async_step_hassio(self, discovery_info: HassioServiceInfo) -> FlowResult:
|
||||||
"""Prepare configuration for a Hass.io AdGuard Home add-on.
|
"""Prepare configuration for a Hass.io AdGuard Home add-on.
|
||||||
|
|
||||||
This flow is triggered by the discovery component.
|
This flow is triggered by the discovery component.
|
||||||
"""
|
"""
|
||||||
await self._async_handle_discovery_without_unique_id()
|
await self._async_handle_discovery_without_unique_id()
|
||||||
|
|
||||||
self._hassio_discovery = discovery_info
|
self._hassio_discovery = discovery_info.config
|
||||||
return await self.async_step_hassio_confirm()
|
return await self.async_step_hassio_confirm()
|
||||||
|
|
||||||
async def async_step_hassio_confirm(
|
async def async_step_hassio_confirm(
|
||||||
|
28
homeassistant/components/adguard/translations/ja.json
Normal file
28
homeassistant/components/adguard/translations/ja.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "\u30b5\u30fc\u30d3\u30b9\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059",
|
||||||
|
"existing_instance_updated": "\u65e2\u5b58\u306e\u8a2d\u5b9a\u3092\u66f4\u65b0\u3057\u307e\u3057\u305f\u3002"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"hassio_confirm": {
|
||||||
|
"description": "\u30a2\u30c9\u30aa\u30f3 {addon} \u304c\u3001\u63d0\u4f9b\u3059\u308bAdGuard Home\u306b\u63a5\u7d9a\u3059\u308b\u3088\u3046\u306bHome Assistant\u3092\u8a2d\u5b9a\u3057\u307e\u3059\u304b\uff1f",
|
||||||
|
"title": "Home Assistant\u30a2\u30c9\u30aa\u30f3\u7d4c\u7531\u306eAdGuard Home"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"host": "\u30db\u30b9\u30c8",
|
||||||
|
"password": "\u30d1\u30b9\u30ef\u30fc\u30c9",
|
||||||
|
"port": "\u30dd\u30fc\u30c8",
|
||||||
|
"ssl": "SSL\u8a3c\u660e\u66f8\u3092\u4f7f\u7528\u3059\u308b",
|
||||||
|
"username": "\u30e6\u30fc\u30b6\u30fc\u540d",
|
||||||
|
"verify_ssl": "SSL\u8a3c\u660e\u66f8\u3092\u78ba\u8a8d\u3059\u308b"
|
||||||
|
},
|
||||||
|
"description": "\u76e3\u8996\u3068\u5236\u5fa1\u304c\u3067\u304d\u308b\u3088\u3046\u306b\u3001AdGuardHome\u30a4\u30f3\u30b9\u30bf\u30f3\u30b9\u306e\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3092\u3057\u307e\u3059\u3002"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,16 +1,27 @@
|
|||||||
{
|
{
|
||||||
"config": {
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "Hizmet zaten yap\u0131land\u0131r\u0131lm\u0131\u015f",
|
||||||
|
"existing_instance_updated": "Mevcut yap\u0131land\u0131rma g\u00fcncellendi."
|
||||||
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"cannot_connect": "Ba\u011flanma hatas\u0131"
|
"cannot_connect": "Ba\u011flanma hatas\u0131"
|
||||||
},
|
},
|
||||||
"step": {
|
"step": {
|
||||||
|
"hassio_confirm": {
|
||||||
|
"description": "{addon} taraf\u0131ndan sa\u011flanan AdGuard Home'a ba\u011flanmak i\u00e7in Home Assistant'\u0131 yap\u0131land\u0131rmak istiyor musunuz?",
|
||||||
|
"title": "Home Assistant eklentisi arac\u0131l\u0131\u011f\u0131yla AdGuard Home"
|
||||||
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
"host": "Ana Bilgisayar",
|
"host": "Ana bilgisayar",
|
||||||
"password": "Parola",
|
"password": "Parola",
|
||||||
"port": "Port",
|
"port": "Port",
|
||||||
"username": "Kullan\u0131c\u0131 Ad\u0131"
|
"ssl": "SSL sertifikas\u0131 kullan\u0131r",
|
||||||
}
|
"username": "Kullan\u0131c\u0131 Ad\u0131",
|
||||||
|
"verify_ssl": "SSL sertifikas\u0131n\u0131 do\u011frulay\u0131n"
|
||||||
|
},
|
||||||
|
"description": "AdGuard Home \u00f6rne\u011finizi, izleme ve kontrole izin verecek \u015fekilde ayarlay\u0131n."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -307,7 +307,7 @@ class AdsEntity(Entity):
|
|||||||
self._ads_hub.add_device_notification, ads_var, plctype, update
|
self._ads_hub.add_device_notification, ads_var, plctype, update
|
||||||
)
|
)
|
||||||
try:
|
try:
|
||||||
with async_timeout.timeout(10):
|
async with async_timeout.timeout(10):
|
||||||
await self._event.wait()
|
await self._event.wait()
|
||||||
except asyncio.TimeoutError:
|
except asyncio.TimeoutError:
|
||||||
_LOGGER.debug("Variable %s: Timeout during first update", ads_var)
|
_LOGGER.debug("Variable %s: Timeout during first update", ads_var)
|
||||||
|
@ -5,14 +5,21 @@ import logging
|
|||||||
|
|
||||||
from advantage_air import ApiError, advantage_air
|
from advantage_air import ApiError, advantage_air
|
||||||
|
|
||||||
from homeassistant.const import CONF_IP_ADDRESS, CONF_PORT
|
from homeassistant.const import CONF_IP_ADDRESS, CONF_PORT, Platform
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
|
|
||||||
from .const import ADVANTAGE_AIR_RETRY, DOMAIN
|
from .const import ADVANTAGE_AIR_RETRY, DOMAIN
|
||||||
|
|
||||||
ADVANTAGE_AIR_SYNC_INTERVAL = 15
|
ADVANTAGE_AIR_SYNC_INTERVAL = 15
|
||||||
PLATFORMS = ["binary_sensor", "climate", "cover", "select", "sensor", "switch"]
|
PLATFORMS = [
|
||||||
|
Platform.BINARY_SENSOR,
|
||||||
|
Platform.CLIMATE,
|
||||||
|
Platform.COVER,
|
||||||
|
Platform.SELECT,
|
||||||
|
Platform.SENSOR,
|
||||||
|
Platform.SWITCH,
|
||||||
|
]
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ from homeassistant.components.climate.const import (
|
|||||||
HVAC_MODE_DRY,
|
HVAC_MODE_DRY,
|
||||||
HVAC_MODE_FAN_ONLY,
|
HVAC_MODE_FAN_ONLY,
|
||||||
HVAC_MODE_HEAT,
|
HVAC_MODE_HEAT,
|
||||||
|
HVAC_MODE_HEAT_COOL,
|
||||||
HVAC_MODE_OFF,
|
HVAC_MODE_OFF,
|
||||||
SUPPORT_FAN_MODE,
|
SUPPORT_FAN_MODE,
|
||||||
SUPPORT_TARGET_TEMPERATURE,
|
SUPPORT_TARGET_TEMPERATURE,
|
||||||
@ -53,7 +54,7 @@ HASS_FAN_MODES = {v: k for k, v in ADVANTAGE_AIR_FAN_MODES.items()}
|
|||||||
FAN_SPEEDS = {FAN_LOW: 30, FAN_MEDIUM: 60, FAN_HIGH: 100}
|
FAN_SPEEDS = {FAN_LOW: 30, FAN_MEDIUM: 60, FAN_HIGH: 100}
|
||||||
|
|
||||||
ADVANTAGE_AIR_SERVICE_SET_MYZONE = "set_myzone"
|
ADVANTAGE_AIR_SERVICE_SET_MYZONE = "set_myzone"
|
||||||
ZONE_HVAC_MODES = [HVAC_MODE_OFF, HVAC_MODE_FAN_ONLY]
|
ZONE_HVAC_MODES = [HVAC_MODE_OFF, HVAC_MODE_HEAT_COOL]
|
||||||
|
|
||||||
PARALLEL_UPDATES = 0
|
PARALLEL_UPDATES = 0
|
||||||
|
|
||||||
@ -169,7 +170,7 @@ class AdvantageAirZone(AdvantageAirClimateEntity):
|
|||||||
def hvac_mode(self):
|
def hvac_mode(self):
|
||||||
"""Return the current state as HVAC mode."""
|
"""Return the current state as HVAC mode."""
|
||||||
if self._zone["state"] == ADVANTAGE_AIR_STATE_OPEN:
|
if self._zone["state"] == ADVANTAGE_AIR_STATE_OPEN:
|
||||||
return HVAC_MODE_FAN_ONLY
|
return HVAC_MODE_HEAT_COOL
|
||||||
return HVAC_MODE_OFF
|
return HVAC_MODE_OFF
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -3,8 +3,8 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
DEVICE_CLASS_TEMPERATURE,
|
DEVICE_CLASS_TEMPERATURE,
|
||||||
STATE_CLASS_MEASUREMENT,
|
|
||||||
SensorEntity,
|
SensorEntity,
|
||||||
|
SensorStateClass,
|
||||||
)
|
)
|
||||||
from homeassistant.const import ENTITY_CATEGORY_DIAGNOSTIC, PERCENTAGE, TEMP_CELSIUS
|
from homeassistant.const import ENTITY_CATEGORY_DIAGNOSTIC, PERCENTAGE, TEMP_CELSIUS
|
||||||
from homeassistant.helpers import config_validation as cv, entity_platform
|
from homeassistant.helpers import config_validation as cv, entity_platform
|
||||||
@ -84,7 +84,7 @@ class AdvantageAirZoneVent(AdvantageAirEntity, SensorEntity):
|
|||||||
"""Representation of Advantage Air Zone Vent Sensor."""
|
"""Representation of Advantage Air Zone Vent Sensor."""
|
||||||
|
|
||||||
_attr_native_unit_of_measurement = PERCENTAGE
|
_attr_native_unit_of_measurement = PERCENTAGE
|
||||||
_attr_state_class = STATE_CLASS_MEASUREMENT
|
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||||
_attr_entity_category = ENTITY_CATEGORY_DIAGNOSTIC
|
_attr_entity_category = ENTITY_CATEGORY_DIAGNOSTIC
|
||||||
|
|
||||||
def __init__(self, instance, ac_key, zone_key):
|
def __init__(self, instance, ac_key, zone_key):
|
||||||
@ -114,7 +114,7 @@ class AdvantageAirZoneSignal(AdvantageAirEntity, SensorEntity):
|
|||||||
"""Representation of Advantage Air Zone wireless signal sensor."""
|
"""Representation of Advantage Air Zone wireless signal sensor."""
|
||||||
|
|
||||||
_attr_native_unit_of_measurement = PERCENTAGE
|
_attr_native_unit_of_measurement = PERCENTAGE
|
||||||
_attr_state_class = STATE_CLASS_MEASUREMENT
|
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||||
_attr_entity_category = ENTITY_CATEGORY_DIAGNOSTIC
|
_attr_entity_category = ENTITY_CATEGORY_DIAGNOSTIC
|
||||||
|
|
||||||
def __init__(self, instance, ac_key, zone_key):
|
def __init__(self, instance, ac_key, zone_key):
|
||||||
@ -149,7 +149,7 @@ class AdvantageAirZoneTemp(AdvantageAirEntity, SensorEntity):
|
|||||||
|
|
||||||
_attr_native_unit_of_measurement = TEMP_CELSIUS
|
_attr_native_unit_of_measurement = TEMP_CELSIUS
|
||||||
_attr_device_class = DEVICE_CLASS_TEMPERATURE
|
_attr_device_class = DEVICE_CLASS_TEMPERATURE
|
||||||
_attr_state_class = STATE_CLASS_MEASUREMENT
|
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||||
_attr_entity_registry_enabled_default = False
|
_attr_entity_registry_enabled_default = False
|
||||||
_attr_entity_category = ENTITY_CATEGORY_DIAGNOSTIC
|
_attr_entity_category = ENTITY_CATEGORY_DIAGNOSTIC
|
||||||
|
|
||||||
|
20
homeassistant/components/advantage_air/translations/ja.json
Normal file
20
homeassistant/components/advantage_air/translations/ja.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "\u30c7\u30d0\u30a4\u30b9\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"ip_address": "IP\u30a2\u30c9\u30ec\u30b9",
|
||||||
|
"port": "\u30dd\u30fc\u30c8"
|
||||||
|
},
|
||||||
|
"description": "Advantage Air wall mounted tablet\u306eAPI\u306b\u63a5\u7d9a\u3057\u307e\u3059\u3002",
|
||||||
|
"title": "\u63a5\u7d9a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -9,9 +9,10 @@
|
|||||||
"step": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
"ip_address": "\u0130p Adresi",
|
"ip_address": "IP Adresi",
|
||||||
"port": "Port"
|
"port": "Port"
|
||||||
},
|
},
|
||||||
|
"description": "Advantage Air duvara monte tabletinizin API'sine ba\u011flan\u0131n.",
|
||||||
"title": "Ba\u011flan"
|
"title": "Ba\u011flan"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,7 @@
|
|||||||
"""Constant values for the AEMET OpenData component."""
|
"""Constant values for the AEMET OpenData component."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import SensorEntityDescription, SensorStateClass
|
||||||
STATE_CLASS_MEASUREMENT,
|
|
||||||
SensorEntityDescription,
|
|
||||||
)
|
|
||||||
from homeassistant.components.weather import (
|
from homeassistant.components.weather import (
|
||||||
ATTR_CONDITION_CLEAR_NIGHT,
|
ATTR_CONDITION_CLEAR_NIGHT,
|
||||||
ATTR_CONDITION_CLOUDY,
|
ATTR_CONDITION_CLOUDY,
|
||||||
@ -36,11 +33,12 @@ from homeassistant.const import (
|
|||||||
PRESSURE_HPA,
|
PRESSURE_HPA,
|
||||||
SPEED_KILOMETERS_PER_HOUR,
|
SPEED_KILOMETERS_PER_HOUR,
|
||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
|
Platform,
|
||||||
)
|
)
|
||||||
|
|
||||||
ATTRIBUTION = "Powered by AEMET OpenData"
|
ATTRIBUTION = "Powered by AEMET OpenData"
|
||||||
CONF_STATION_UPDATES = "station_updates"
|
CONF_STATION_UPDATES = "station_updates"
|
||||||
PLATFORMS = ["sensor", "weather"]
|
PLATFORMS = [Platform.SENSOR, Platform.WEATHER]
|
||||||
DEFAULT_NAME = "AEMET"
|
DEFAULT_NAME = "AEMET"
|
||||||
DOMAIN = "aemet"
|
DOMAIN = "aemet"
|
||||||
ENTRY_NAME = "name"
|
ENTRY_NAME = "name"
|
||||||
@ -255,14 +253,14 @@ WEATHER_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
|
|||||||
name="Humidity",
|
name="Humidity",
|
||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
device_class=DEVICE_CLASS_HUMIDITY,
|
device_class=DEVICE_CLASS_HUMIDITY,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=ATTR_API_PRESSURE,
|
key=ATTR_API_PRESSURE,
|
||||||
name="Pressure",
|
name="Pressure",
|
||||||
native_unit_of_measurement=PRESSURE_HPA,
|
native_unit_of_measurement=PRESSURE_HPA,
|
||||||
device_class=DEVICE_CLASS_PRESSURE,
|
device_class=DEVICE_CLASS_PRESSURE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=ATTR_API_RAIN,
|
key=ATTR_API_RAIN,
|
||||||
@ -273,7 +271,7 @@ WEATHER_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
|
|||||||
key=ATTR_API_RAIN_PROB,
|
key=ATTR_API_RAIN_PROB,
|
||||||
name="Rain probability",
|
name="Rain probability",
|
||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=ATTR_API_SNOW,
|
key=ATTR_API_SNOW,
|
||||||
@ -284,7 +282,7 @@ WEATHER_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
|
|||||||
key=ATTR_API_SNOW_PROB,
|
key=ATTR_API_SNOW_PROB,
|
||||||
name="Snow probability",
|
name="Snow probability",
|
||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=ATTR_API_STATION_ID,
|
key=ATTR_API_STATION_ID,
|
||||||
@ -303,21 +301,21 @@ WEATHER_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
|
|||||||
key=ATTR_API_STORM_PROB,
|
key=ATTR_API_STORM_PROB,
|
||||||
name="Storm probability",
|
name="Storm probability",
|
||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=ATTR_API_TEMPERATURE,
|
key=ATTR_API_TEMPERATURE,
|
||||||
name="Temperature",
|
name="Temperature",
|
||||||
native_unit_of_measurement=TEMP_CELSIUS,
|
native_unit_of_measurement=TEMP_CELSIUS,
|
||||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=ATTR_API_TEMPERATURE_FEELING,
|
key=ATTR_API_TEMPERATURE_FEELING,
|
||||||
name="Temperature feeling",
|
name="Temperature feeling",
|
||||||
native_unit_of_measurement=TEMP_CELSIUS,
|
native_unit_of_measurement=TEMP_CELSIUS,
|
||||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=ATTR_API_TOWN_ID,
|
key=ATTR_API_TOWN_ID,
|
||||||
@ -336,7 +334,7 @@ WEATHER_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
|
|||||||
key=ATTR_API_WIND_BEARING,
|
key=ATTR_API_WIND_BEARING,
|
||||||
name="Wind bearing",
|
name="Wind bearing",
|
||||||
native_unit_of_measurement=DEGREE,
|
native_unit_of_measurement=DEGREE,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=ATTR_API_WIND_MAX_SPEED,
|
key=ATTR_API_WIND_MAX_SPEED,
|
||||||
@ -347,7 +345,7 @@ WEATHER_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
|
|||||||
key=ATTR_API_WIND_SPEED,
|
key=ATTR_API_WIND_SPEED,
|
||||||
name="Wind speed",
|
name="Wind speed",
|
||||||
native_unit_of_measurement=SPEED_KILOMETERS_PER_HOUR,
|
native_unit_of_measurement=SPEED_KILOMETERS_PER_HOUR,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
14
homeassistant/components/aemet/translations/bg.json
Normal file
14
homeassistant/components/aemet/translations/bg.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"error": {
|
||||||
|
"invalid_api_key": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d API \u043a\u043b\u044e\u0447"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"api_key": "API \u043a\u043b\u044e\u0447"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
31
homeassistant/components/aemet/translations/ja.json
Normal file
31
homeassistant/components/aemet/translations/ja.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"invalid_api_key": "\u7121\u52b9\u306aAPI\u30ad\u30fc"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"api_key": "API\u30ad\u30fc",
|
||||||
|
"latitude": "\u7def\u5ea6",
|
||||||
|
"longitude": "\u7d4c\u5ea6",
|
||||||
|
"name": "\u30a4\u30f3\u30c6\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u306e\u540d\u524d"
|
||||||
|
},
|
||||||
|
"description": "AEMET OpenData\u30a4\u30f3\u30c6\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u3092\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3057\u307e\u3059\u3002 API\u30ad\u30fc\u3092\u751f\u6210\u3059\u308b\u306b\u306f\u3001https://opendata.aemet.es/centrodedescargas/altaUsuario \u306b\u30a2\u30af\u30bb\u30b9\u3057\u3066\u304f\u3060\u3055\u3044",
|
||||||
|
"title": "AEMET OpenData"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"step": {
|
||||||
|
"init": {
|
||||||
|
"data": {
|
||||||
|
"station_updates": "AEMET weather station\u304b\u3089\u30c7\u30fc\u30bf\u3092\u53ce\u96c6\u3059\u308b"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@
|
|||||||
"longitude": "\u0414\u043e\u043b\u0433\u043e\u0442\u0430",
|
"longitude": "\u0414\u043e\u043b\u0433\u043e\u0442\u0430",
|
||||||
"name": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435"
|
"name": "\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435"
|
||||||
},
|
},
|
||||||
"description": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 Home Assistant \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 AEMET OpenData. \u0427\u0442\u043e\u0431\u044b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u044e\u0447 API, \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043d\u0430 https://opendata.aemet.es/centrodedescargas/altaUsuario.",
|
"description": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0430 Home Assistant \u0434\u043b\u044f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 \u0441 AEMET OpenData. \u0427\u0442\u043e\u0431\u044b \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043a\u043b\u044e\u0447 API, \u043f\u0435\u0440\u0435\u0439\u0434\u0438\u0442\u0435 \u043d\u0430 https://opendata.aemet.es/centrodedescargas/altaUsuario.",
|
||||||
"title": "AEMET OpenData"
|
"title": "AEMET OpenData"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
31
homeassistant/components/aemet/translations/tr.json
Normal file
31
homeassistant/components/aemet/translations/tr.json
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "Konum zaten yap\u0131land\u0131r\u0131lm\u0131\u015f"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"invalid_api_key": "Ge\u00e7ersiz API anahtar\u0131"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"api_key": "API Anahtar\u0131",
|
||||||
|
"latitude": "Enlem",
|
||||||
|
"longitude": "Boylam",
|
||||||
|
"name": "Entegrasyonun ad\u0131"
|
||||||
|
},
|
||||||
|
"description": "AEMET OpenData entegrasyonunu ayarlay\u0131n. API anahtar\u0131 olu\u015fturmak i\u00e7in https://opendata.aemet.es/centrodedescargas/altaUsuario adresine gidin.",
|
||||||
|
"title": "AEMET OpenData"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"step": {
|
||||||
|
"init": {
|
||||||
|
"data": {
|
||||||
|
"station_updates": "AEMET hava istasyonlar\u0131ndan veri toplay\u0131n"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -140,7 +140,7 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
|
|
||||||
async def _async_update_data(self):
|
async def _async_update_data(self):
|
||||||
data = {}
|
data = {}
|
||||||
with async_timeout.timeout(120):
|
async with async_timeout.timeout(120):
|
||||||
weather_response = await self._get_aemet_weather()
|
weather_response = await self._get_aemet_weather()
|
||||||
data = self._convert_weather_response(weather_response)
|
data = self._convert_weather_response(weather_response)
|
||||||
return data
|
return data
|
||||||
@ -398,8 +398,7 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def _convert_forecast_day(self, date, day):
|
def _convert_forecast_day(self, date, day):
|
||||||
condition = self._get_condition_day(day)
|
if not (condition := self._get_condition_day(day)):
|
||||||
if not condition:
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -415,8 +414,7 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
}
|
}
|
||||||
|
|
||||||
def _convert_forecast_hour(self, date, day, hour):
|
def _convert_forecast_hour(self, date, day, hour):
|
||||||
condition = self._get_condition(day, hour)
|
if not (condition := self._get_condition(day, hour)):
|
||||||
if not condition:
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
forecast_dt = date.replace(hour=hour, minute=0, second=0)
|
forecast_dt = date.replace(hour=hour, minute=0, second=0)
|
||||||
@ -435,13 +433,8 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
|
|
||||||
def _calc_precipitation(self, day, hour):
|
def _calc_precipitation(self, day, hour):
|
||||||
"""Calculate the precipitation."""
|
"""Calculate the precipitation."""
|
||||||
rain_value = self._get_rain(day, hour)
|
rain_value = self._get_rain(day, hour) or 0
|
||||||
if not rain_value:
|
snow_value = self._get_snow(day, hour) or 0
|
||||||
rain_value = 0
|
|
||||||
|
|
||||||
snow_value = self._get_snow(day, hour)
|
|
||||||
if not snow_value:
|
|
||||||
snow_value = 0
|
|
||||||
|
|
||||||
if round(rain_value + snow_value, 1) == 0:
|
if round(rain_value + snow_value, 1) == 0:
|
||||||
return None
|
return None
|
||||||
@ -449,13 +442,8 @@ class WeatherUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
|
|
||||||
def _calc_precipitation_prob(self, day, hour):
|
def _calc_precipitation_prob(self, day, hour):
|
||||||
"""Calculate the precipitation probability (hour)."""
|
"""Calculate the precipitation probability (hour)."""
|
||||||
rain_value = self._get_rain_prob(day, hour)
|
rain_value = self._get_rain_prob(day, hour) or 0
|
||||||
if not rain_value:
|
snow_value = self._get_snow_prob(day, hour) or 0
|
||||||
rain_value = 0
|
|
||||||
|
|
||||||
snow_value = self._get_snow_prob(day, hour)
|
|
||||||
if not snow_value:
|
|
||||||
snow_value = 0
|
|
||||||
|
|
||||||
if rain_value == 0 and snow_value == 0:
|
if rain_value == 0 and snow_value == 0:
|
||||||
return None
|
return None
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
from agent import AgentError
|
from agent import AgentError
|
||||||
from agent.a import Agent
|
from agent.a import Agent
|
||||||
|
|
||||||
|
from homeassistant.const import Platform
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
from homeassistant.helpers import device_registry as dr
|
from homeassistant.helpers import device_registry as dr
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
@ -12,7 +13,7 @@ from .const import CONNECTION, DOMAIN as AGENT_DOMAIN, SERVER_URL
|
|||||||
ATTRIBUTION = "ispyconnect.com"
|
ATTRIBUTION = "ispyconnect.com"
|
||||||
DEFAULT_BRAND = "Agent DVR by ispyconnect.com"
|
DEFAULT_BRAND = "Agent DVR by ispyconnect.com"
|
||||||
|
|
||||||
FORWARDS = ["alarm_control_panel", "camera"]
|
PLATFORMS = [Platform.ALARM_CONTROL_PANEL, Platform.CAMERA]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass, config_entry):
|
async def async_setup_entry(hass, config_entry):
|
||||||
@ -35,7 +36,7 @@ async def async_setup_entry(hass, config_entry):
|
|||||||
|
|
||||||
hass.data[AGENT_DOMAIN][config_entry.entry_id] = {CONNECTION: agent_client}
|
hass.data[AGENT_DOMAIN][config_entry.entry_id] = {CONNECTION: agent_client}
|
||||||
|
|
||||||
device_registry = await dr.async_get_registry(hass)
|
device_registry = dr.async_get(hass)
|
||||||
|
|
||||||
device_registry.async_get_or_create(
|
device_registry.async_get_or_create(
|
||||||
config_entry_id=config_entry.entry_id,
|
config_entry_id=config_entry.entry_id,
|
||||||
@ -46,14 +47,16 @@ async def async_setup_entry(hass, config_entry):
|
|||||||
sw_version=agent_client.version,
|
sw_version=agent_client.version,
|
||||||
)
|
)
|
||||||
|
|
||||||
hass.config_entries.async_setup_platforms(config_entry, FORWARDS)
|
hass.config_entries.async_setup_platforms(config_entry, PLATFORMS)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
async def async_unload_entry(hass, config_entry):
|
async def async_unload_entry(hass, config_entry):
|
||||||
"""Unload a config entry."""
|
"""Unload a config entry."""
|
||||||
unload_ok = await hass.config_entries.async_unload_platforms(config_entry, FORWARDS)
|
unload_ok = await hass.config_entries.async_unload_platforms(
|
||||||
|
config_entry, PLATFORMS
|
||||||
|
)
|
||||||
|
|
||||||
await hass.data[AGENT_DOMAIN][config_entry.entry_id][CONNECTION].close()
|
await hass.data[AGENT_DOMAIN][config_entry.entry_id][CONNECTION].close()
|
||||||
|
|
||||||
|
20
homeassistant/components/agent_dvr/translations/ja.json
Normal file
20
homeassistant/components/agent_dvr/translations/ja.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "\u30c7\u30d0\u30a4\u30b9\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"already_in_progress": "\u69cb\u6210\u30d5\u30ed\u30fc\u306f\u3059\u3067\u306b\u9032\u884c\u4e2d\u3067\u3059",
|
||||||
|
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"host": "\u30db\u30b9\u30c8",
|
||||||
|
"port": "\u30dd\u30fc\u30c8"
|
||||||
|
},
|
||||||
|
"title": "Agent DVR\u3092\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -10,7 +10,7 @@
|
|||||||
"step": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
"host": "Ana Bilgisayar",
|
"host": "Ana bilgisayar",
|
||||||
"port": "Port"
|
"port": "Port"
|
||||||
},
|
},
|
||||||
"title": "Agent DVR'\u0131 kurun"
|
"title": "Agent DVR'\u0131 kurun"
|
||||||
|
@ -137,8 +137,7 @@ class AirQualityEntity(Entity):
|
|||||||
data: dict[str, str | int | float] = {}
|
data: dict[str, str | int | float] = {}
|
||||||
|
|
||||||
for prop, attr in PROP_TO_ATTR.items():
|
for prop, attr in PROP_TO_ATTR.items():
|
||||||
value = getattr(self, prop)
|
if (value := getattr(self, prop)) is not None:
|
||||||
if value is not None:
|
|
||||||
data[attr] = value
|
data[attr] = value
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
@ -13,7 +13,7 @@ import async_timeout
|
|||||||
|
|
||||||
from homeassistant.components.air_quality import DOMAIN as AIR_QUALITY_PLATFORM
|
from homeassistant.components.air_quality import DOMAIN as AIR_QUALITY_PLATFORM
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE
|
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers import entity_registry
|
from homeassistant.helpers import entity_registry
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
@ -33,7 +33,7 @@ from .const import (
|
|||||||
NO_AIRLY_SENSORS,
|
NO_AIRLY_SENSORS,
|
||||||
)
|
)
|
||||||
|
|
||||||
PLATFORMS = ["sensor"]
|
PLATFORMS = [Platform.SENSOR]
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -167,7 +167,7 @@ class AirlyDataUpdateCoordinator(DataUpdateCoordinator):
|
|||||||
measurements = self.airly.create_measurements_session_point(
|
measurements = self.airly.create_measurements_session_point(
|
||||||
self.latitude, self.longitude
|
self.latitude, self.longitude
|
||||||
)
|
)
|
||||||
with async_timeout.timeout(20):
|
async with async_timeout.timeout(20):
|
||||||
try:
|
try:
|
||||||
await measurements.update()
|
await measurements.update()
|
||||||
except (AirlyError, ClientConnectorError) as error:
|
except (AirlyError, ClientConnectorError) as error:
|
||||||
|
@ -103,7 +103,7 @@ async def test_location(
|
|||||||
measurements = airly.create_measurements_session_point(
|
measurements = airly.create_measurements_session_point(
|
||||||
latitude=latitude, longitude=longitude
|
latitude=latitude, longitude=longitude
|
||||||
)
|
)
|
||||||
with async_timeout.timeout(10):
|
async with async_timeout.timeout(10):
|
||||||
await measurements.update()
|
await measurements.update()
|
||||||
|
|
||||||
current = measurements.current
|
current = measurements.current
|
||||||
|
@ -27,6 +27,7 @@ from homeassistant.const import (
|
|||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
|
from homeassistant.helpers.device_registry import DeviceEntryType
|
||||||
from homeassistant.helpers.entity import DeviceInfo
|
from homeassistant.helpers.entity import DeviceInfo
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
from homeassistant.helpers.typing import StateType
|
from homeassistant.helpers.typing import StateType
|
||||||
@ -154,7 +155,7 @@ class AirlySensor(CoordinatorEntity, SensorEntity):
|
|||||||
"""Initialize."""
|
"""Initialize."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
self._attr_device_info = DeviceInfo(
|
self._attr_device_info = DeviceInfo(
|
||||||
entry_type="service",
|
entry_type=DeviceEntryType.SERVICE,
|
||||||
identifiers={(DOMAIN, f"{coordinator.latitude}-{coordinator.longitude}")},
|
identifiers={(DOMAIN, f"{coordinator.latitude}-{coordinator.longitude}")},
|
||||||
manufacturer=MANUFACTURER,
|
manufacturer=MANUFACTURER,
|
||||||
name=DEFAULT_NAME,
|
name=DEFAULT_NAME,
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
{
|
{
|
||||||
"config": {
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "\u041c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435\u0442\u043e \u0432\u0435\u0447\u0435 \u0435 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u0430\u043d\u043e"
|
||||||
|
},
|
||||||
"error": {
|
"error": {
|
||||||
|
"invalid_api_key": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d API \u043a\u043b\u044e\u0447",
|
||||||
"wrong_location": "\u0412 \u0442\u0430\u0437\u0438 \u043e\u0431\u043b\u0430\u0441\u0442 \u043d\u044f\u043c\u0430 \u0438\u0437\u043c\u0435\u0440\u0432\u0430\u0442\u0435\u043b\u043d\u0438 \u0441\u0442\u0430\u043d\u0446\u0438\u0438 \u043d\u0430 Airly."
|
"wrong_location": "\u0412 \u0442\u0430\u0437\u0438 \u043e\u0431\u043b\u0430\u0441\u0442 \u043d\u044f\u043c\u0430 \u0438\u0437\u043c\u0435\u0440\u0432\u0430\u0442\u0435\u043b\u043d\u0438 \u0441\u0442\u0430\u043d\u0446\u0438\u0438 \u043d\u0430 Airly."
|
||||||
},
|
},
|
||||||
"step": {
|
"step": {
|
||||||
|
30
homeassistant/components/airly/translations/ja.json
Normal file
30
homeassistant/components/airly/translations/ja.json
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"invalid_api_key": "\u7121\u52b9\u306aAPI\u30ad\u30fc",
|
||||||
|
"wrong_location": "\u3053\u306e\u30a8\u30ea\u30a2\u306b\u3001Airly\u306e\u6e2c\u5b9a\u30b9\u30c6\u30fc\u30b7\u30e7\u30f3\u306f\u3042\u308a\u307e\u305b\u3093\u3002"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"api_key": "API\u30ad\u30fc",
|
||||||
|
"latitude": "\u7def\u5ea6",
|
||||||
|
"longitude": "\u7d4c\u5ea6",
|
||||||
|
"name": "\u540d\u524d"
|
||||||
|
},
|
||||||
|
"description": "Airly\u306e\u7a7a\u6c17\u54c1\u8cea\u30a4\u30f3\u30c6\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u3092\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3057\u307e\u3059\u3002 API\u30ad\u30fc\u3092\u751f\u6210\u3059\u308b\u306b\u306f\u3001https://developer.airly.eu/register \u306b\u30a2\u30af\u30bb\u30b9\u3057\u3066\u304f\u3060\u3055\u3044",
|
||||||
|
"title": "Airly"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"system_health": {
|
||||||
|
"info": {
|
||||||
|
"can_reach_server": "Airly\u30b5\u30fc\u30d0\u30fc\u306b\u5230\u9054",
|
||||||
|
"requests_per_day": "1\u65e5\u3042\u305f\u308a\u306e\u8a31\u53ef\u3055\u308c\u305f\u30ea\u30af\u30a8\u30b9\u30c8",
|
||||||
|
"requests_remaining": "\u6b8b\u308a\u306e\u8a31\u53ef\u3055\u308c\u305f\u30ea\u30af\u30a8\u30b9\u30c8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -4,21 +4,27 @@
|
|||||||
"already_configured": "Konum zaten yap\u0131land\u0131r\u0131lm\u0131\u015f"
|
"already_configured": "Konum zaten yap\u0131land\u0131r\u0131lm\u0131\u015f"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"invalid_api_key": "Ge\u00e7ersiz API anahtar\u0131"
|
"invalid_api_key": "Ge\u00e7ersiz API anahtar\u0131",
|
||||||
|
"wrong_location": "Bu b\u00f6lgede Airly \u00f6l\u00e7\u00fcm istasyonu yok."
|
||||||
},
|
},
|
||||||
"step": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
"api_key": "API Anahtar\u0131",
|
"api_key": "API Anahtar\u0131",
|
||||||
"latitude": "Enlem",
|
"latitude": "Enlem",
|
||||||
"longitude": "Boylam"
|
"longitude": "Boylam",
|
||||||
}
|
"name": "Ad"
|
||||||
|
},
|
||||||
|
"description": "Airly hava kalitesi entegrasyonunu ayarlay\u0131n. API anahtar\u0131 olu\u015fturmak i\u00e7in https://developer.airly.eu/register adresine gidin.",
|
||||||
|
"title": "Airly"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"system_health": {
|
"system_health": {
|
||||||
"info": {
|
"info": {
|
||||||
"can_reach_server": "Airly sunucusuna eri\u015fin"
|
"can_reach_server": "Airly sunucusuna eri\u015fin",
|
||||||
|
"requests_per_day": "G\u00fcnl\u00fck izin verilen istek say\u0131s\u0131",
|
||||||
|
"requests_remaining": "Kalan izin verilen istekler"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -8,7 +8,13 @@ from pyairnow.conv import aqi_to_concentration
|
|||||||
from pyairnow.errors import AirNowError
|
from pyairnow.errors import AirNowError
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_API_KEY, CONF_LATITUDE, CONF_LONGITUDE, CONF_RADIUS
|
from homeassistant.const import (
|
||||||
|
CONF_API_KEY,
|
||||||
|
CONF_LATITUDE,
|
||||||
|
CONF_LONGITUDE,
|
||||||
|
CONF_RADIUS,
|
||||||
|
Platform,
|
||||||
|
)
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
@ -33,7 +39,7 @@ from .const import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
PLATFORMS = ["sensor"]
|
PLATFORMS = [Platform.SENSOR]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
@ -86,7 +86,8 @@ class AirNowSensor(CoordinatorEntity, SensorEntity):
|
|||||||
@property
|
@property
|
||||||
def native_value(self):
|
def native_value(self):
|
||||||
"""Return the state."""
|
"""Return the state."""
|
||||||
self._state = self.coordinator.data[self.entity_description.key]
|
self._state = self.coordinator.data.get(self.entity_description.key)
|
||||||
|
|
||||||
return self._state
|
return self._state
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
26
homeassistant/components/airnow/translations/ja.json
Normal file
26
homeassistant/components/airnow/translations/ja.json
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "\u30c7\u30d0\u30a4\u30b9\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f",
|
||||||
|
"invalid_auth": "\u7121\u52b9\u306a\u8a8d\u8a3c",
|
||||||
|
"invalid_location": "\u305d\u306e\u5834\u6240\u306b\u5bfe\u3059\u308b\u7d50\u679c\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093",
|
||||||
|
"unknown": "\u4e88\u671f\u3057\u306a\u3044\u30a8\u30e9\u30fc"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"api_key": "API\u30ad\u30fc",
|
||||||
|
"latitude": "\u7def\u5ea6",
|
||||||
|
"longitude": "\u7d4c\u5ea6",
|
||||||
|
"radius": "\u30b9\u30c6\u30fc\u30b7\u30e7\u30f3\u534a\u5f84(\u30de\u30a4\u30eb; \u30aa\u30d7\u30b7\u30e7\u30f3)"
|
||||||
|
},
|
||||||
|
"description": "AirNow\u306e\u7a7a\u6c17\u54c1\u8cea\u30a4\u30f3\u30c6\u30b0\u30ec\u30fc\u30b7\u30e7\u30f3\u3092\u30bb\u30c3\u30c8\u30a2\u30c3\u30d7\u3057\u307e\u3059\u3002 API\u30ad\u30fc\u3092\u751f\u6210\u3059\u308b\u306b\u306f\u3001https://docs.airnowapi.org/account/request/ \u306b\u30a2\u30af\u30bb\u30b9\u3057\u3066\u304f\u3060\u3055\u3044",
|
||||||
|
"title": "AirNow"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"title": "AirNow"
|
||||||
|
}
|
@ -17,6 +17,7 @@
|
|||||||
"longitude": "Boylam",
|
"longitude": "Boylam",
|
||||||
"radius": "\u0130stasyon Yar\u0131\u00e7ap\u0131 (mil; iste\u011fe ba\u011fl\u0131)"
|
"radius": "\u0130stasyon Yar\u0131\u00e7ap\u0131 (mil; iste\u011fe ba\u011fl\u0131)"
|
||||||
},
|
},
|
||||||
|
"description": "AirNow hava kalitesi entegrasyonunu ayarlay\u0131n. API anahtar\u0131 olu\u015fturmak i\u00e7in https://docs.airnowapi.org/account/request/ adresine gidin.",
|
||||||
"title": "AirNow"
|
"title": "AirNow"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import logging
|
|||||||
from airthings import Airthings, AirthingsError
|
from airthings import Airthings, AirthingsError
|
||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
@ -15,7 +16,7 @@ from .const import CONF_ID, CONF_SECRET, DOMAIN
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
PLATFORMS: list[str] = ["sensor"]
|
PLATFORMS: list[Platform] = [Platform.SENSOR]
|
||||||
SCAN_INTERVAL = timedelta(minutes=6)
|
SCAN_INTERVAL = timedelta(minutes=6)
|
||||||
|
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
"name": "Airthings",
|
"name": "Airthings",
|
||||||
"config_flow": true,
|
"config_flow": true,
|
||||||
"documentation": "https://www.home-assistant.io/integrations/airthings",
|
"documentation": "https://www.home-assistant.io/integrations/airthings",
|
||||||
"requirements": ["airthings_cloud==0.0.1"],
|
"requirements": ["airthings_cloud==0.1.0"],
|
||||||
"codeowners": [
|
"codeowners": [
|
||||||
"@danielhiversen"
|
"@danielhiversen"
|
||||||
],
|
],
|
||||||
|
@ -4,9 +4,10 @@ from __future__ import annotations
|
|||||||
from airthings import AirthingsDevice
|
from airthings import AirthingsDevice
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
STATE_CLASS_MEASUREMENT,
|
SensorDeviceClass,
|
||||||
SensorEntity,
|
SensorEntity,
|
||||||
SensorEntityDescription,
|
SensorEntityDescription,
|
||||||
|
SensorStateClass,
|
||||||
StateType,
|
StateType,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
@ -14,14 +15,6 @@ from homeassistant.const import (
|
|||||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
CONCENTRATION_PARTS_PER_BILLION,
|
CONCENTRATION_PARTS_PER_BILLION,
|
||||||
CONCENTRATION_PARTS_PER_MILLION,
|
CONCENTRATION_PARTS_PER_MILLION,
|
||||||
DEVICE_CLASS_BATTERY,
|
|
||||||
DEVICE_CLASS_CO2,
|
|
||||||
DEVICE_CLASS_HUMIDITY,
|
|
||||||
DEVICE_CLASS_PM1,
|
|
||||||
DEVICE_CLASS_PM25,
|
|
||||||
DEVICE_CLASS_PRESSURE,
|
|
||||||
DEVICE_CLASS_SIGNAL_STRENGTH,
|
|
||||||
DEVICE_CLASS_TEMPERATURE,
|
|
||||||
ENTITY_CATEGORY_DIAGNOSTIC,
|
ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
PERCENTAGE,
|
PERCENTAGE,
|
||||||
PRESSURE_MBAR,
|
PRESSURE_MBAR,
|
||||||
@ -46,32 +39,32 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
|||||||
),
|
),
|
||||||
"temp": SensorEntityDescription(
|
"temp": SensorEntityDescription(
|
||||||
key="temp",
|
key="temp",
|
||||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
device_class=SensorDeviceClass.TEMPERATURE,
|
||||||
native_unit_of_measurement=TEMP_CELSIUS,
|
native_unit_of_measurement=TEMP_CELSIUS,
|
||||||
name="Temperature",
|
name="Temperature",
|
||||||
),
|
),
|
||||||
"humidity": SensorEntityDescription(
|
"humidity": SensorEntityDescription(
|
||||||
key="humidity",
|
key="humidity",
|
||||||
device_class=DEVICE_CLASS_HUMIDITY,
|
device_class=SensorDeviceClass.HUMIDITY,
|
||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
name="Humidity",
|
name="Humidity",
|
||||||
),
|
),
|
||||||
"pressure": SensorEntityDescription(
|
"pressure": SensorEntityDescription(
|
||||||
key="pressure",
|
key="pressure",
|
||||||
device_class=DEVICE_CLASS_PRESSURE,
|
device_class=SensorDeviceClass.PRESSURE,
|
||||||
native_unit_of_measurement=PRESSURE_MBAR,
|
native_unit_of_measurement=PRESSURE_MBAR,
|
||||||
name="Pressure",
|
name="Pressure",
|
||||||
),
|
),
|
||||||
"battery": SensorEntityDescription(
|
"battery": SensorEntityDescription(
|
||||||
key="battery",
|
key="battery",
|
||||||
device_class=DEVICE_CLASS_BATTERY,
|
device_class=SensorDeviceClass.BATTERY,
|
||||||
native_unit_of_measurement=PERCENTAGE,
|
native_unit_of_measurement=PERCENTAGE,
|
||||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
name="Battery",
|
name="Battery",
|
||||||
),
|
),
|
||||||
"co2": SensorEntityDescription(
|
"co2": SensorEntityDescription(
|
||||||
key="co2",
|
key="co2",
|
||||||
device_class=DEVICE_CLASS_CO2,
|
device_class=SensorDeviceClass.CO2,
|
||||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||||
name="CO2",
|
name="CO2",
|
||||||
),
|
),
|
||||||
@ -96,7 +89,7 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
|||||||
"rssi": SensorEntityDescription(
|
"rssi": SensorEntityDescription(
|
||||||
key="rssi",
|
key="rssi",
|
||||||
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
|
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
|
||||||
device_class=DEVICE_CLASS_SIGNAL_STRENGTH,
|
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
||||||
name="RSSI",
|
name="RSSI",
|
||||||
entity_registry_enabled_default=False,
|
entity_registry_enabled_default=False,
|
||||||
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
entity_category=ENTITY_CATEGORY_DIAGNOSTIC,
|
||||||
@ -104,13 +97,13 @@ SENSORS: dict[str, SensorEntityDescription] = {
|
|||||||
"pm1": SensorEntityDescription(
|
"pm1": SensorEntityDescription(
|
||||||
key="pm1",
|
key="pm1",
|
||||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
device_class=DEVICE_CLASS_PM1,
|
device_class=SensorDeviceClass.PM1,
|
||||||
name="PM1",
|
name="PM1",
|
||||||
),
|
),
|
||||||
"pm25": SensorEntityDescription(
|
"pm25": SensorEntityDescription(
|
||||||
key="pm25",
|
key="pm25",
|
||||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
device_class=DEVICE_CLASS_PM25,
|
device_class=SensorDeviceClass.PM25,
|
||||||
name="PM25",
|
name="PM25",
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
@ -140,7 +133,7 @@ async def async_setup_entry(
|
|||||||
class AirthingsHeaterEnergySensor(CoordinatorEntity, SensorEntity):
|
class AirthingsHeaterEnergySensor(CoordinatorEntity, SensorEntity):
|
||||||
"""Representation of a Airthings Sensor device."""
|
"""Representation of a Airthings Sensor device."""
|
||||||
|
|
||||||
_attr_state_class = STATE_CLASS_MEASUREMENT
|
_attr_state_class = SensorStateClass.MEASUREMENT
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
21
homeassistant/components/airthings/translations/id.json
Normal file
21
homeassistant/components/airthings/translations/id.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "Akun sudah dikonfigurasi"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "Gagal terhubung",
|
||||||
|
"invalid_auth": "Autentikasi tidak valid",
|
||||||
|
"unknown": "Kesalahan yang tidak diharapkan"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"description": "Masuk di {url} untuk menemukan kredensial Anda",
|
||||||
|
"id": "ID",
|
||||||
|
"secret": "Kode Rahasia"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
21
homeassistant/components/airthings/translations/ja.json
Normal file
21
homeassistant/components/airthings/translations/ja.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "\u30a2\u30ab\u30a6\u30f3\u30c8\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f",
|
||||||
|
"invalid_auth": "\u7121\u52b9\u306a\u8a8d\u8a3c",
|
||||||
|
"unknown": "\u4e88\u671f\u3057\u306a\u3044\u30a8\u30e9\u30fc"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"description": "{url} \u306b\u30ed\u30b0\u30a4\u30f3\u3057\u3066\u3001\u8cc7\u683c\u60c5\u5831\u3092\u78ba\u8a8d\u3057\u3066\u304f\u3060\u3055\u3044",
|
||||||
|
"id": "ID",
|
||||||
|
"secret": "\u30b7\u30fc\u30af\u30ec\u30c3\u30c8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@
|
|||||||
"step": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
|
"description": "Zaloguj si\u0119 pod {url}, aby znale\u017a\u0107 swoje dane uwierzytelniaj\u0105ce",
|
||||||
"id": "ID",
|
"id": "ID",
|
||||||
"secret": "Sekret"
|
"secret": "Sekret"
|
||||||
}
|
}
|
||||||
|
21
homeassistant/components/airthings/translations/tr.json
Normal file
21
homeassistant/components/airthings/translations/tr.json
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "Hesap zaten yap\u0131land\u0131r\u0131lm\u0131\u015f"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "Ba\u011flanma hatas\u0131",
|
||||||
|
"invalid_auth": "Ge\u00e7ersiz kimlik do\u011frulama",
|
||||||
|
"unknown": "Beklenmeyen hata"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"description": "Kimlik bilgilerinizi bulmak i\u00e7in {url} adresinden giri\u015f yap\u0131n",
|
||||||
|
"id": "ID",
|
||||||
|
"secret": "Gizli"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -6,7 +6,7 @@ from airtouch4pyapi.airtouch import AirTouchStatus
|
|||||||
|
|
||||||
from homeassistant.components.climate import SCAN_INTERVAL
|
from homeassistant.components.climate import SCAN_INTERVAL
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import CONF_HOST
|
from homeassistant.const import CONF_HOST, Platform
|
||||||
from homeassistant.core import HomeAssistant
|
from homeassistant.core import HomeAssistant
|
||||||
from homeassistant.exceptions import ConfigEntryNotReady
|
from homeassistant.exceptions import ConfigEntryNotReady
|
||||||
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
|
||||||
@ -15,7 +15,7 @@ from .const import DOMAIN
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
PLATFORMS = ["climate"]
|
PLATFORMS = [Platform.CLIMATE]
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
|
@ -4,13 +4,15 @@
|
|||||||
"already_configured": "Perangkat sudah dikonfigurasi"
|
"already_configured": "Perangkat sudah dikonfigurasi"
|
||||||
},
|
},
|
||||||
"error": {
|
"error": {
|
||||||
"cannot_connect": "Gagal terhubung"
|
"cannot_connect": "Gagal terhubung",
|
||||||
|
"no_units": "Tidak dapat menemukan Grup AirTouch 4 apa pun."
|
||||||
},
|
},
|
||||||
"step": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
"host": "Host"
|
"host": "Host"
|
||||||
}
|
},
|
||||||
|
"title": "Siapkan detail koneksi AirTouch 4 Anda."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
homeassistant/components/airtouch4/translations/ja.json
Normal file
19
homeassistant/components/airtouch4/translations/ja.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "\u30c7\u30d0\u30a4\u30b9\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f",
|
||||||
|
"no_units": "AirTouch 4 Groups\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093\u3067\u3057\u305f\u3002"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"host": "\u30db\u30b9\u30c8"
|
||||||
|
},
|
||||||
|
"title": "AirTouch 4\u63a5\u7d9a\u306e\u8a73\u7d30\u8a2d\u5b9a\u3092\u3057\u307e\u3059\u3002"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
19
homeassistant/components/airtouch4/translations/tr.json
Normal file
19
homeassistant/components/airtouch4/translations/tr.json
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "Cihaz zaten yap\u0131land\u0131r\u0131lm\u0131\u015f"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "Ba\u011flanma hatas\u0131",
|
||||||
|
"no_units": "Herhangi bir AirTouch 4 Grubu bulunamad\u0131."
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"host": "Ana bilgisayar"
|
||||||
|
},
|
||||||
|
"title": "AirTouch 4 ba\u011flant\u0131 ayr\u0131nt\u0131lar\u0131n\u0131z\u0131 ayarlay\u0131n."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -16,7 +16,6 @@ from pyairvisual.errors import (
|
|||||||
|
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ATTRIBUTION,
|
|
||||||
CONF_API_KEY,
|
CONF_API_KEY,
|
||||||
CONF_IP_ADDRESS,
|
CONF_IP_ADDRESS,
|
||||||
CONF_LATITUDE,
|
CONF_LATITUDE,
|
||||||
@ -24,6 +23,7 @@ from homeassistant.const import (
|
|||||||
CONF_PASSWORD,
|
CONF_PASSWORD,
|
||||||
CONF_SHOW_ON_MAP,
|
CONF_SHOW_ON_MAP,
|
||||||
CONF_STATE,
|
CONF_STATE,
|
||||||
|
Platform,
|
||||||
)
|
)
|
||||||
from homeassistant.core import HomeAssistant, callback
|
from homeassistant.core import HomeAssistant, callback
|
||||||
from homeassistant.exceptions import ConfigEntryAuthFailed
|
from homeassistant.exceptions import ConfigEntryAuthFailed
|
||||||
@ -52,7 +52,7 @@ from .const import (
|
|||||||
LOGGER,
|
LOGGER,
|
||||||
)
|
)
|
||||||
|
|
||||||
PLATFORMS = ["sensor"]
|
PLATFORMS = [Platform.SENSOR]
|
||||||
|
|
||||||
DEFAULT_ATTRIBUTION = "Data provided by AirVisual"
|
DEFAULT_ATTRIBUTION = "Data provided by AirVisual"
|
||||||
DEFAULT_NODE_PRO_UPDATE_INTERVAL = timedelta(minutes=1)
|
DEFAULT_NODE_PRO_UPDATE_INTERVAL = timedelta(minutes=1)
|
||||||
@ -191,9 +191,6 @@ def _standardize_node_pro_config_entry(hass: HomeAssistant, entry: ConfigEntry)
|
|||||||
|
|
||||||
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
||||||
"""Set up AirVisual as config entry."""
|
"""Set up AirVisual as config entry."""
|
||||||
hass.data.setdefault(DOMAIN, {})
|
|
||||||
hass.data[DOMAIN][entry.entry_id] = {}
|
|
||||||
|
|
||||||
if CONF_API_KEY in entry.data:
|
if CONF_API_KEY in entry.data:
|
||||||
_standardize_geography_config_entry(hass, entry)
|
_standardize_geography_config_entry(hass, entry)
|
||||||
|
|
||||||
@ -272,7 +269,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||||||
)
|
)
|
||||||
|
|
||||||
await coordinator.async_config_entry_first_refresh()
|
await coordinator.async_config_entry_first_refresh()
|
||||||
hass.data[DOMAIN][entry.entry_id][DATA_COORDINATOR] = coordinator
|
hass.data.setdefault(DOMAIN, {})
|
||||||
|
hass.data[DOMAIN][entry.entry_id] = {DATA_COORDINATOR: coordinator}
|
||||||
|
|
||||||
# Reassess the interval between 2 server requests
|
# Reassess the interval between 2 server requests
|
||||||
if CONF_API_KEY in entry.data:
|
if CONF_API_KEY in entry.data:
|
||||||
@ -356,7 +354,7 @@ class AirVisualEntity(CoordinatorEntity):
|
|||||||
"""Initialize."""
|
"""Initialize."""
|
||||||
super().__init__(coordinator)
|
super().__init__(coordinator)
|
||||||
|
|
||||||
self._attr_extra_state_attributes = {ATTR_ATTRIBUTION: DEFAULT_ATTRIBUTION}
|
self._attr_extra_state_attributes = {}
|
||||||
self._entry = entry
|
self._entry = entry
|
||||||
self.entity_description = description
|
self.entity_description = description
|
||||||
|
|
||||||
|
@ -91,6 +91,7 @@ class AirVisualFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
self, user_input: dict[str, str], integration_type: str
|
self, user_input: dict[str, str], integration_type: str
|
||||||
) -> FlowResult:
|
) -> FlowResult:
|
||||||
"""Validate a Cloud API key."""
|
"""Validate a Cloud API key."""
|
||||||
|
errors = {}
|
||||||
websession = aiohttp_client.async_get_clientsession(self.hass)
|
websession = aiohttp_client.async_get_clientsession(self.hass)
|
||||||
cloud_api = CloudAPI(user_input[CONF_API_KEY], session=websession)
|
cloud_api = CloudAPI(user_input[CONF_API_KEY], session=websession)
|
||||||
|
|
||||||
@ -117,27 +118,20 @@ class AirVisualFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
|
|||||||
try:
|
try:
|
||||||
await coro
|
await coro
|
||||||
except InvalidKeyError:
|
except InvalidKeyError:
|
||||||
return self.async_show_form(
|
errors[CONF_API_KEY] = "invalid_api_key"
|
||||||
step_id=error_step,
|
|
||||||
data_schema=error_schema,
|
|
||||||
errors={CONF_API_KEY: "invalid_api_key"},
|
|
||||||
)
|
|
||||||
except NotFoundError:
|
except NotFoundError:
|
||||||
return self.async_show_form(
|
errors[CONF_CITY] = "location_not_found"
|
||||||
step_id=error_step,
|
|
||||||
data_schema=error_schema,
|
|
||||||
errors={CONF_CITY: "location_not_found"},
|
|
||||||
)
|
|
||||||
except AirVisualError as err:
|
except AirVisualError as err:
|
||||||
LOGGER.error(err)
|
LOGGER.error(err)
|
||||||
return self.async_show_form(
|
errors["base"] = "unknown"
|
||||||
step_id=error_step,
|
|
||||||
data_schema=error_schema,
|
|
||||||
errors={"base": "unknown"},
|
|
||||||
)
|
|
||||||
|
|
||||||
valid_keys.add(user_input[CONF_API_KEY])
|
valid_keys.add(user_input[CONF_API_KEY])
|
||||||
|
|
||||||
|
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)
|
existing_entry = await self.async_set_unique_id(self._geo_id)
|
||||||
if existing_entry:
|
if existing_entry:
|
||||||
self.hass.config_entries.async_update_entry(existing_entry, data=user_input)
|
self.hass.config_entries.async_update_entry(existing_entry, data=user_input)
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from homeassistant.components.sensor import (
|
from homeassistant.components.sensor import (
|
||||||
STATE_CLASS_MEASUREMENT,
|
|
||||||
SensorEntity,
|
SensorEntity,
|
||||||
SensorEntityDescription,
|
SensorEntityDescription,
|
||||||
|
SensorStateClass,
|
||||||
)
|
)
|
||||||
from homeassistant.config_entries import ConfigEntry
|
from homeassistant.config_entries import ConfigEntry
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
@ -81,7 +81,7 @@ GEOGRAPHY_SENSOR_DESCRIPTIONS = (
|
|||||||
name="Air Quality Index",
|
name="Air Quality Index",
|
||||||
device_class=DEVICE_CLASS_AQI,
|
device_class=DEVICE_CLASS_AQI,
|
||||||
native_unit_of_measurement="AQI",
|
native_unit_of_measurement="AQI",
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=SENSOR_KIND_POLLUTANT,
|
key=SENSOR_KIND_POLLUTANT,
|
||||||
@ -98,7 +98,7 @@ NODE_PRO_SENSOR_DESCRIPTIONS = (
|
|||||||
name="Air Quality Index",
|
name="Air Quality Index",
|
||||||
device_class=DEVICE_CLASS_AQI,
|
device_class=DEVICE_CLASS_AQI,
|
||||||
native_unit_of_measurement="AQI",
|
native_unit_of_measurement="AQI",
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=SENSOR_KIND_BATTERY_LEVEL,
|
key=SENSOR_KIND_BATTERY_LEVEL,
|
||||||
@ -112,7 +112,7 @@ NODE_PRO_SENSOR_DESCRIPTIONS = (
|
|||||||
name="C02",
|
name="C02",
|
||||||
device_class=DEVICE_CLASS_CO2,
|
device_class=DEVICE_CLASS_CO2,
|
||||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=SENSOR_KIND_HUMIDITY,
|
key=SENSOR_KIND_HUMIDITY,
|
||||||
@ -125,35 +125,35 @@ NODE_PRO_SENSOR_DESCRIPTIONS = (
|
|||||||
name="PM 0.1",
|
name="PM 0.1",
|
||||||
device_class=DEVICE_CLASS_PM1,
|
device_class=DEVICE_CLASS_PM1,
|
||||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=SENSOR_KIND_PM_1_0,
|
key=SENSOR_KIND_PM_1_0,
|
||||||
name="PM 1.0",
|
name="PM 1.0",
|
||||||
device_class=DEVICE_CLASS_PM10,
|
device_class=DEVICE_CLASS_PM10,
|
||||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=SENSOR_KIND_PM_2_5,
|
key=SENSOR_KIND_PM_2_5,
|
||||||
name="PM 2.5",
|
name="PM 2.5",
|
||||||
device_class=DEVICE_CLASS_PM25,
|
device_class=DEVICE_CLASS_PM25,
|
||||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=SENSOR_KIND_TEMPERATURE,
|
key=SENSOR_KIND_TEMPERATURE,
|
||||||
name="Temperature",
|
name="Temperature",
|
||||||
device_class=DEVICE_CLASS_TEMPERATURE,
|
device_class=DEVICE_CLASS_TEMPERATURE,
|
||||||
native_unit_of_measurement=TEMP_CELSIUS,
|
native_unit_of_measurement=TEMP_CELSIUS,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
SensorEntityDescription(
|
SensorEntityDescription(
|
||||||
key=SENSOR_KIND_VOC,
|
key=SENSOR_KIND_VOC,
|
||||||
name="VOC",
|
name="VOC",
|
||||||
device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
|
device_class=DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS,
|
||||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||||
state_class=STATE_CLASS_MEASUREMENT,
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,8 +9,14 @@
|
|||||||
"invalid_api_key": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d API \u043a\u043b\u044e\u0447"
|
"invalid_api_key": "\u041d\u0435\u0432\u0430\u043b\u0438\u0434\u0435\u043d API \u043a\u043b\u044e\u0447"
|
||||||
},
|
},
|
||||||
"step": {
|
"step": {
|
||||||
|
"geography_by_coords": {
|
||||||
|
"data": {
|
||||||
|
"api_key": "API \u043a\u043b\u044e\u0447"
|
||||||
|
}
|
||||||
|
},
|
||||||
"geography_by_name": {
|
"geography_by_name": {
|
||||||
"data": {
|
"data": {
|
||||||
|
"api_key": "API \u043a\u043b\u044e\u0447",
|
||||||
"city": "\u0413\u0440\u0430\u0434",
|
"city": "\u0413\u0440\u0430\u0434",
|
||||||
"country": "\u0421\u0442\u0440\u0430\u043d\u0430"
|
"country": "\u0421\u0442\u0440\u0430\u043d\u0430"
|
||||||
}
|
}
|
||||||
|
63
homeassistant/components/airvisual/translations/ja.json
Normal file
63
homeassistant/components/airvisual/translations/ja.json
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
{
|
||||||
|
"config": {
|
||||||
|
"abort": {
|
||||||
|
"already_configured": "\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u306f\u3059\u3067\u306b\u8a2d\u5b9a\u3055\u308c\u3066\u3044\u307e\u3059\u3002\u307e\u305f\u306f\u3001Node/Pro ID\u306f\u65e2\u306b\u767b\u9332\u3055\u308c\u3066\u3044\u307e\u3059\u3002",
|
||||||
|
"reauth_successful": "\u518d\u8a8d\u8a3c\u306b\u6210\u529f\u3057\u307e\u3057\u305f"
|
||||||
|
},
|
||||||
|
"error": {
|
||||||
|
"cannot_connect": "\u63a5\u7d9a\u306b\u5931\u6557\u3057\u307e\u3057\u305f",
|
||||||
|
"general_error": "\u4e88\u671f\u3057\u306a\u3044\u30a8\u30e9\u30fc",
|
||||||
|
"invalid_api_key": "\u7121\u52b9\u306aAPI\u30ad\u30fc",
|
||||||
|
"location_not_found": "\u30ed\u30b1\u30fc\u30b7\u30e7\u30f3\u304c\u898b\u3064\u304b\u308a\u307e\u305b\u3093"
|
||||||
|
},
|
||||||
|
"step": {
|
||||||
|
"geography_by_coords": {
|
||||||
|
"data": {
|
||||||
|
"api_key": "API\u30ad\u30fc",
|
||||||
|
"latitude": "\u7def\u5ea6",
|
||||||
|
"longitude": "\u7d4c\u5ea6"
|
||||||
|
},
|
||||||
|
"description": "AirVisual cloud API\u3092\u4f7f\u7528\u3057\u3066\u3001\u7def\u5ea6/\u7d4c\u5ea6\u3092\u76e3\u8996\u3057\u307e\u3059\u3002",
|
||||||
|
"title": "Geography\u306e\u8a2d\u5b9a"
|
||||||
|
},
|
||||||
|
"geography_by_name": {
|
||||||
|
"data": {
|
||||||
|
"api_key": "API\u30ad\u30fc",
|
||||||
|
"city": "\u90fd\u5e02",
|
||||||
|
"country": "\u56fd",
|
||||||
|
"state": "\u5dde"
|
||||||
|
},
|
||||||
|
"description": "AirVisual cloud API\u3092\u4f7f\u7528\u3057\u3066\u3001\u90fd\u5e02/\u5dde/\u56fd\u3092\u76e3\u8996\u3057\u307e\u3059\u3002",
|
||||||
|
"title": "Geography\u306e\u8a2d\u5b9a"
|
||||||
|
},
|
||||||
|
"node_pro": {
|
||||||
|
"data": {
|
||||||
|
"ip_address": "\u30db\u30b9\u30c8",
|
||||||
|
"password": "\u30d1\u30b9\u30ef\u30fc\u30c9"
|
||||||
|
},
|
||||||
|
"description": "\u500b\u4eba\u306eAirVisual\u30e6\u30cb\u30c3\u30c8\u3092\u76e3\u8996\u3057\u307e\u3059\u3002\u30d1\u30b9\u30ef\u30fc\u30c9\u306f\u3001\u672c\u4f53\u306eUI\u304b\u3089\u53d6\u5f97\u3067\u304d\u307e\u3059\u3002",
|
||||||
|
"title": "AirVisual Node/Pro\u306e\u8a2d\u5b9a"
|
||||||
|
},
|
||||||
|
"reauth_confirm": {
|
||||||
|
"data": {
|
||||||
|
"api_key": "API\u30ad\u30fc"
|
||||||
|
},
|
||||||
|
"title": "AirVisual\u3092\u518d\u8a8d\u8a3c"
|
||||||
|
},
|
||||||
|
"user": {
|
||||||
|
"description": "\u76e3\u8996\u3057\u305f\u3044\u3001AirVisual\u306e\u30c7\u30fc\u30bf\u306e\u7a2e\u985e\u3092\u9078\u629e\u3057\u307e\u3059\u3002",
|
||||||
|
"title": "AirVisual\u306e\u8a2d\u5b9a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"options": {
|
||||||
|
"step": {
|
||||||
|
"init": {
|
||||||
|
"data": {
|
||||||
|
"show_on_map": "\u76e3\u8996\u5bfe\u8c61\u306e\u5730\u7406\u3092\u5730\u56f3\u306b\u8868\u793a"
|
||||||
|
},
|
||||||
|
"title": "AirVisual\u306e\u8a2d\u5b9a"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,20 @@
|
|||||||
{
|
{
|
||||||
"state": {
|
"state": {
|
||||||
"airvisual__pollutant_label": {
|
"airvisual__pollutant_label": {
|
||||||
|
"co": "\u0412\u044a\u0433\u043b\u0435\u0440\u043e\u0434\u0435\u043d \u043e\u043a\u0438\u0441",
|
||||||
|
"n2": "\u0410\u0437\u043e\u0442\u0435\u043d \u0434\u0438\u043e\u043a\u0441\u0438\u0434",
|
||||||
"o3": "\u041e\u0437\u043e\u043d",
|
"o3": "\u041e\u0437\u043e\u043d",
|
||||||
"p1": "PM10",
|
"p1": "PM10",
|
||||||
"p2": "PM2.5"
|
"p2": "PM2.5",
|
||||||
|
"s2": "\u0421\u0435\u0440\u0435\u043d \u0434\u0438\u043e\u043a\u0441\u0438\u0434"
|
||||||
|
},
|
||||||
|
"airvisual__pollutant_level": {
|
||||||
|
"good": "\u0414\u043e\u0431\u0440\u043e",
|
||||||
|
"hazardous": "\u041e\u043f\u0430\u0441\u043d\u043e",
|
||||||
|
"moderate": "\u0423\u043c\u0435\u0440\u0435\u043d\u043e",
|
||||||
|
"unhealthy": "\u041d\u0435\u0437\u0434\u0440\u0430\u0432\u043e\u0441\u043b\u043e\u0432\u043d\u043e",
|
||||||
|
"unhealthy_sensitive": "\u041d\u0435\u0437\u0434\u0440\u0430\u0432\u043e\u0441\u043b\u043e\u0432\u043d\u043e \u0437\u0430 \u0447\u0443\u0432\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u043d\u0438 \u0433\u0440\u0443\u043f\u0438",
|
||||||
|
"very_unhealthy": "\u041c\u043d\u043e\u0433\u043e \u043d\u0435\u0437\u0434\u0440\u0430\u0432\u043e\u0441\u043b\u043e\u0432\u043d\u043e"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"state": {
|
||||||
|
"airvisual__pollutant_label": {
|
||||||
|
"co": "Karbon monoksida",
|
||||||
|
"n2": "Nitrogen dioksida",
|
||||||
|
"o3": "Ozon",
|
||||||
|
"p1": "PM10",
|
||||||
|
"p2": "PM2.5",
|
||||||
|
"s2": "Sulfur Dioksida"
|
||||||
|
},
|
||||||
|
"airvisual__pollutant_level": {
|
||||||
|
"good": "Bagus",
|
||||||
|
"hazardous": "Berbahaya",
|
||||||
|
"moderate": "Sedang",
|
||||||
|
"unhealthy": "Tidak sehat",
|
||||||
|
"unhealthy_sensitive": "Tidak sehat untuk kelompok sensitif",
|
||||||
|
"very_unhealthy": "Sangat tidak sehat"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user