Merge pull request #36626 from home-assistant/rc

This commit is contained in:
Franck Nijhof 2020-06-10 16:07:38 +02:00 committed by GitHub
commit 818b45384d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2169 changed files with 30978 additions and 11564 deletions

View File

@ -10,6 +10,14 @@ omit =
# omit pieces of code that rely on external devices being present # omit pieces of code that rely on external devices being present
homeassistant/components/acer_projector/switch.py homeassistant/components/acer_projector/switch.py
homeassistant/components/actiontec/device_tracker.py homeassistant/components/actiontec/device_tracker.py
homeassistant/components/acmeda/__init__.py
homeassistant/components/acmeda/base.py
homeassistant/components/acmeda/const.py
homeassistant/components/acmeda/cover.py
homeassistant/components/acmeda/errors.py
homeassistant/components/acmeda/helpers.py
homeassistant/components/acmeda/hub.py
homeassistant/components/acmeda/sensor.py
homeassistant/components/adguard/__init__.py homeassistant/components/adguard/__init__.py
homeassistant/components/adguard/const.py homeassistant/components/adguard/const.py
homeassistant/components/adguard/sensor.py homeassistant/components/adguard/sensor.py
@ -55,14 +63,9 @@ omit =
homeassistant/components/arwn/sensor.py homeassistant/components/arwn/sensor.py
homeassistant/components/asterisk_cdr/mailbox.py homeassistant/components/asterisk_cdr/mailbox.py
homeassistant/components/asterisk_mbox/* homeassistant/components/asterisk_mbox/*
homeassistant/components/atag/__init__.py
homeassistant/components/atag/climate.py
homeassistant/components/atag/sensor.py
homeassistant/components/atag/water_heater.py
homeassistant/components/aten_pe/* homeassistant/components/aten_pe/*
homeassistant/components/atome/* homeassistant/components/atome/*
homeassistant/components/aurora_abb_powerone/sensor.py homeassistant/components/aurora_abb_powerone/sensor.py
homeassistant/components/automatic/*
homeassistant/components/avea/light.py homeassistant/components/avea/light.py
homeassistant/components/avion/light.py homeassistant/components/avion/light.py
homeassistant/components/avri/sensor.py homeassistant/components/avri/sensor.py
@ -115,6 +118,7 @@ omit =
homeassistant/components/cast/* homeassistant/components/cast/*
homeassistant/components/cert_expiry/helper.py homeassistant/components/cert_expiry/helper.py
homeassistant/components/channels/* homeassistant/components/channels/*
homeassistant/components/circuit/*
homeassistant/components/cisco_ios/device_tracker.py homeassistant/components/cisco_ios/device_tracker.py
homeassistant/components/cisco_mobility_express/device_tracker.py homeassistant/components/cisco_mobility_express/device_tracker.py
homeassistant/components/cisco_webex_teams/notify.py homeassistant/components/cisco_webex_teams/notify.py
@ -172,6 +176,8 @@ omit =
homeassistant/components/dsmr_reader/* homeassistant/components/dsmr_reader/*
homeassistant/components/dte_energy_bridge/sensor.py homeassistant/components/dte_energy_bridge/sensor.py
homeassistant/components/dublin_bus_transport/sensor.py homeassistant/components/dublin_bus_transport/sensor.py
homeassistant/components/dunehd/__init__.py
homeassistant/components/dunehd/const.py
homeassistant/components/dunehd/media_player.py homeassistant/components/dunehd/media_player.py
homeassistant/components/dwd_weather_warnings/sensor.py homeassistant/components/dwd_weather_warnings/sensor.py
homeassistant/components/dweet/* homeassistant/components/dweet/*
@ -271,7 +277,6 @@ omit =
homeassistant/components/garmin_connect/sensor.py homeassistant/components/garmin_connect/sensor.py
homeassistant/components/gc100/* homeassistant/components/gc100/*
homeassistant/components/geniushub/* homeassistant/components/geniushub/*
homeassistant/components/gearbest/sensor.py
homeassistant/components/geizhals/sensor.py homeassistant/components/geizhals/sensor.py
homeassistant/components/gios/__init__.py homeassistant/components/gios/__init__.py
homeassistant/components/gios/air_quality.py homeassistant/components/gios/air_quality.py
@ -282,7 +287,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/gogogate2/cover.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
@ -296,6 +300,10 @@ omit =
homeassistant/components/growatt_server/sensor.py homeassistant/components/growatt_server/sensor.py
homeassistant/components/gstreamer/media_player.py homeassistant/components/gstreamer/media_player.py
homeassistant/components/gtfs/sensor.py homeassistant/components/gtfs/sensor.py
homeassistant/components/guardian/__init__.py
homeassistant/components/guardian/binary_sensor.py
homeassistant/components/guardian/sensor.py
homeassistant/components/guardian/switch.py
homeassistant/components/habitica/* homeassistant/components/habitica/*
homeassistant/components/hangouts/* homeassistant/components/hangouts/*
homeassistant/components/hangouts/__init__.py homeassistant/components/hangouts/__init__.py
@ -557,7 +565,9 @@ omit =
homeassistant/components/openevse/sensor.py homeassistant/components/openevse/sensor.py
homeassistant/components/openexchangerates/sensor.py homeassistant/components/openexchangerates/sensor.py
homeassistant/components/opengarage/cover.py homeassistant/components/opengarage/cover.py
homeassistant/components/openhome/__init__.py
homeassistant/components/openhome/media_player.py homeassistant/components/openhome/media_player.py
homeassistant/components/openhome/const.py
homeassistant/components/opensensemap/air_quality.py homeassistant/components/opensensemap/air_quality.py
homeassistant/components/opensky/sensor.py homeassistant/components/opensky/sensor.py
homeassistant/components/opentherm_gw/__init__.py homeassistant/components/opentherm_gw/__init__.py
@ -595,7 +605,11 @@ omit =
homeassistant/components/plaato/* homeassistant/components/plaato/*
homeassistant/components/plex/media_player.py homeassistant/components/plex/media_player.py
homeassistant/components/plex/sensor.py homeassistant/components/plex/sensor.py
homeassistant/components/plugwise/* homeassistant/components/plugwise/__init__.py
homeassistant/components/plugwise/binary_sensor.py
homeassistant/components/plugwise/climate.py
homeassistant/components/plugwise/sensor.py
homeassistant/components/plugwise/switch.py
homeassistant/components/plum_lightpad/* homeassistant/components/plum_lightpad/*
homeassistant/components/pocketcasts/sensor.py homeassistant/components/pocketcasts/sensor.py
homeassistant/components/point/* homeassistant/components/point/*
@ -718,7 +732,6 @@ omit =
homeassistant/components/soma/__init__.py homeassistant/components/soma/__init__.py
homeassistant/components/somfy/* homeassistant/components/somfy/*
homeassistant/components/somfy_mylink/* homeassistant/components/somfy_mylink/*
homeassistant/components/sonarr/sensor.py
homeassistant/components/sonos/* homeassistant/components/sonos/*
homeassistant/components/sony_projector/switch.py homeassistant/components/sony_projector/switch.py
homeassistant/components/spc/* homeassistant/components/spc/*
@ -748,6 +761,7 @@ omit =
homeassistant/components/synology/camera.py homeassistant/components/synology/camera.py
homeassistant/components/synology_chat/notify.py homeassistant/components/synology_chat/notify.py
homeassistant/components/synology_dsm/__init__.py homeassistant/components/synology_dsm/__init__.py
homeassistant/components/synology_dsm/binary_sensor.py
homeassistant/components/synology_dsm/sensor.py homeassistant/components/synology_dsm/sensor.py
homeassistant/components/synology_srm/device_tracker.py homeassistant/components/synology_srm/device_tracker.py
homeassistant/components/syslog/notify.py homeassistant/components/syslog/notify.py
@ -872,9 +886,6 @@ omit =
homeassistant/components/wirelesstag/* homeassistant/components/wirelesstag/*
homeassistant/components/worldtidesinfo/sensor.py homeassistant/components/worldtidesinfo/sensor.py
homeassistant/components/worxlandroid/sensor.py homeassistant/components/worxlandroid/sensor.py
homeassistant/components/wunderlist/*
homeassistant/components/wwlln/__init__.py
homeassistant/components/wwlln/geo_location.py
homeassistant/components/x10/light.py homeassistant/components/x10/light.py
homeassistant/components/xbox_live/sensor.py homeassistant/components/xbox_live/sensor.py
homeassistant/components/xeoma/camera.py homeassistant/components/xeoma/camera.py
@ -922,7 +933,7 @@ omit =
homeassistant/components/zha/light.py homeassistant/components/zha/light.py
homeassistant/components/zha/sensor.py homeassistant/components/zha/sensor.py
homeassistant/components/zhong_hong/climate.py homeassistant/components/zhong_hong/climate.py
homeassistant/components/zigbee/* homeassistant/components/xbee/*
homeassistant/components/ziggo_mediabox_xl/media_player.py homeassistant/components/ziggo_mediabox_xl/media_player.py
homeassistant/components/zoneminder/* homeassistant/components/zoneminder/*
homeassistant/components/supla/* homeassistant/components/supla/*

1
.gitignore vendored
View File

@ -106,6 +106,7 @@ virtualization/vagrant/config
!.vscode/cSpell.json !.vscode/cSpell.json
!.vscode/extensions.json !.vscode/extensions.json
!.vscode/tasks.json !.vscode/tasks.json
.env
# Built docs # Built docs
docs/build docs/build

View File

@ -22,7 +22,7 @@ repos:
- --quiet-level=2 - --quiet-level=2
exclude_types: [csv, json] exclude_types: [csv, json]
- repo: https://gitlab.com/pycqa/flake8 - repo: https://gitlab.com/pycqa/flake8
rev: 3.7.9 rev: 3.8.1
hooks: hooks:
- id: flake8 - id: flake8
additional_dependencies: additional_dependencies:
@ -80,8 +80,8 @@ repos:
entry: script/run-in-env.sh python3 -m script.gen_requirements_all entry: script/run-in-env.sh python3 -m script.gen_requirements_all
pass_filenames: false pass_filenames: false
language: script language: script
types: [json] types: [text]
files: ^homeassistant/.+/manifest\.json$ files: ^(homeassistant/.+/manifest\.json|\.pre-commit-config\.yaml)$
- id: hassfest - id: hassfest
name: hassfest name: hassfest
entry: script/run-in-env.sh python3 -m script.hassfest entry: script/run-in-env.sh python3 -m script.hassfest

View File

@ -14,6 +14,7 @@ homeassistant/scripts/check_config.py @kellerza
# Integrations # Integrations
homeassistant/components/abode/* @shred86 homeassistant/components/abode/* @shred86
homeassistant/components/acmeda/* @atmurray
homeassistant/components/adguard/* @frenck homeassistant/components/adguard/* @frenck
homeassistant/components/agent_dvr/* @ispysoftware homeassistant/components/agent_dvr/* @ispysoftware
homeassistant/components/airly/* @bieniu homeassistant/components/airly/* @bieniu
@ -42,7 +43,6 @@ homeassistant/components/atome/* @baqs
homeassistant/components/august/* @bdraco homeassistant/components/august/* @bdraco
homeassistant/components/aurora_abb_powerone/* @davet2001 homeassistant/components/aurora_abb_powerone/* @davet2001
homeassistant/components/auth/* @home-assistant/core homeassistant/components/auth/* @home-assistant/core
homeassistant/components/automatic/* @armills
homeassistant/components/automation/* @home-assistant/core homeassistant/components/automation/* @home-assistant/core
homeassistant/components/avea/* @pattyland homeassistant/components/avea/* @pattyland
homeassistant/components/avri/* @timvancann homeassistant/components/avri/* @timvancann
@ -68,6 +68,7 @@ homeassistant/components/bt_smarthub/* @jxwolstenholme
homeassistant/components/buienradar/* @mjj4791 @ties homeassistant/components/buienradar/* @mjj4791 @ties
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/cisco_ios/* @fbradyirl homeassistant/components/cisco_ios/* @fbradyirl
homeassistant/components/cisco_mobility_express/* @fbradyirl homeassistant/components/cisco_mobility_express/* @fbradyirl
homeassistant/components/cisco_webex_teams/* @fbradyirl homeassistant/components/cisco_webex_teams/* @fbradyirl
@ -86,7 +87,7 @@ homeassistant/components/cups/* @fabaff
homeassistant/components/daikin/* @fredrike homeassistant/components/daikin/* @fredrike
homeassistant/components/darksky/* @fabaff homeassistant/components/darksky/* @fabaff
homeassistant/components/deconz/* @Kane610 homeassistant/components/deconz/* @Kane610
homeassistant/components/delijn/* @bollewolle homeassistant/components/delijn/* @bollewolle @Emilv2
homeassistant/components/demo/* @home-assistant/core homeassistant/components/demo/* @home-assistant/core
homeassistant/components/denonavr/* @scarface-4711 @starkillerOG homeassistant/components/denonavr/* @scarface-4711 @starkillerOG
homeassistant/components/derivative/* @afaucogney homeassistant/components/derivative/* @afaucogney
@ -97,6 +98,7 @@ homeassistant/components/directv/* @ctalkington
homeassistant/components/discogs/* @thibmaek homeassistant/components/discogs/* @thibmaek
homeassistant/components/doorbird/* @oblogic7 @bdraco homeassistant/components/doorbird/* @oblogic7 @bdraco
homeassistant/components/dsmr_reader/* @depl0y homeassistant/components/dsmr_reader/* @depl0y
homeassistant/components/dunehd/* @bieniu
homeassistant/components/dweet/* @fabaff homeassistant/components/dweet/* @fabaff
homeassistant/components/dynalite/* @ziv1234 homeassistant/components/dynalite/* @ziv1234
homeassistant/components/dyson/* @etheralm homeassistant/components/dyson/* @etheralm
@ -140,7 +142,6 @@ homeassistant/components/fronius/* @nielstron
homeassistant/components/frontend/* @home-assistant/frontend homeassistant/components/frontend/* @home-assistant/frontend
homeassistant/components/garmin_connect/* @cyberjunky homeassistant/components/garmin_connect/* @cyberjunky
homeassistant/components/gdacs/* @exxamalte homeassistant/components/gdacs/* @exxamalte
homeassistant/components/gearbest/* @HerrHofrat
homeassistant/components/geniushub/* @zxdavb homeassistant/components/geniushub/* @zxdavb
homeassistant/components/geo_rss_events/* @exxamalte homeassistant/components/geo_rss_events/* @exxamalte
homeassistant/components/geonetnz_quakes/* @exxamalte homeassistant/components/geonetnz_quakes/* @exxamalte
@ -149,6 +150,7 @@ homeassistant/components/gios/* @bieniu
homeassistant/components/gitter/* @fabaff homeassistant/components/gitter/* @fabaff
homeassistant/components/glances/* @fabaff @engrbm87 homeassistant/components/glances/* @fabaff @engrbm87
homeassistant/components/gntp/* @robbiet480 homeassistant/components/gntp/* @robbiet480
homeassistant/components/gogogate2/* @vangorra
homeassistant/components/google_assistant/* @home-assistant/cloud homeassistant/components/google_assistant/* @home-assistant/cloud
homeassistant/components/google_cloud/* @lufton homeassistant/components/google_cloud/* @lufton
homeassistant/components/google_translate/* @awarecan homeassistant/components/google_translate/* @awarecan
@ -159,6 +161,7 @@ homeassistant/components/griddy/* @bdraco
homeassistant/components/group/* @home-assistant/core homeassistant/components/group/* @home-assistant/core
homeassistant/components/growatt_server/* @indykoning homeassistant/components/growatt_server/* @indykoning
homeassistant/components/gtfs/* @robbiet480 homeassistant/components/gtfs/* @robbiet480
homeassistant/components/guardian/* @bachya
homeassistant/components/harmony/* @ehendrix23 @bramkragten @bdraco homeassistant/components/harmony/* @ehendrix23 @bramkragten @bdraco
homeassistant/components/hassio/* @home-assistant/hass-io homeassistant/components/hassio/* @home-assistant/hass-io
homeassistant/components/heatmiser/* @andylockran homeassistant/components/heatmiser/* @andylockran
@ -178,7 +181,7 @@ homeassistant/components/homematicip_cloud/* @SukramJ
homeassistant/components/honeywell/* @zxdavb homeassistant/components/honeywell/* @zxdavb
homeassistant/components/html5/* @robbiet480 homeassistant/components/html5/* @robbiet480
homeassistant/components/http/* @home-assistant/core homeassistant/components/http/* @home-assistant/core
homeassistant/components/huawei_lte/* @scop homeassistant/components/huawei_lte/* @scop @fphammerle
homeassistant/components/huawei_router/* @abmantis homeassistant/components/huawei_router/* @abmantis
homeassistant/components/hue/* @balloob homeassistant/components/hue/* @balloob
homeassistant/components/hunterdouglas_powerview/* @bdraco homeassistant/components/hunterdouglas_powerview/* @bdraco
@ -193,6 +196,7 @@ homeassistant/components/input_datetime/* @home-assistant/core
homeassistant/components/input_number/* @home-assistant/core homeassistant/components/input_number/* @home-assistant/core
homeassistant/components/input_select/* @home-assistant/core homeassistant/components/input_select/* @home-assistant/core
homeassistant/components/input_text/* @home-assistant/core homeassistant/components/input_text/* @home-assistant/core
homeassistant/components/insteon/* @teharris1
homeassistant/components/integration/* @dgomes homeassistant/components/integration/* @dgomes
homeassistant/components/intent/* @home-assistant/core homeassistant/components/intent/* @home-assistant/core
homeassistant/components/intesishome/* @jnimmo homeassistant/components/intesishome/* @jnimmo
@ -306,11 +310,11 @@ homeassistant/components/pilight/* @trekky12
homeassistant/components/plaato/* @JohNan homeassistant/components/plaato/* @JohNan
homeassistant/components/plant/* @ChristianKuehnel homeassistant/components/plant/* @ChristianKuehnel
homeassistant/components/plex/* @jjlawren homeassistant/components/plex/* @jjlawren
homeassistant/components/plugwise/* @laetificat @CoMPaTech @bouwew homeassistant/components/plugwise/* @CoMPaTech @bouwew
homeassistant/components/plum_lightpad/* @ColinHarrington homeassistant/components/plum_lightpad/* @ColinHarrington
homeassistant/components/point/* @fredrike homeassistant/components/point/* @fredrike
homeassistant/components/powerwall/* @bdraco @jrester homeassistant/components/powerwall/* @bdraco @jrester
homeassistant/components/proxmoxve/* @k4ds3 homeassistant/components/proxmoxve/* @k4ds3 @jhollowe
homeassistant/components/ps4/* @ktnrg45 homeassistant/components/ps4/* @ktnrg45
homeassistant/components/ptvsd/* @swamp-ig homeassistant/components/ptvsd/* @swamp-ig
homeassistant/components/push/* @dgomes homeassistant/components/push/* @dgomes
@ -370,7 +374,6 @@ homeassistant/components/soma/* @ratsept
homeassistant/components/somfy/* @tetienne homeassistant/components/somfy/* @tetienne
homeassistant/components/sonarr/* @ctalkington homeassistant/components/sonarr/* @ctalkington
homeassistant/components/songpal/* @rytilahti @shenxn homeassistant/components/songpal/* @rytilahti @shenxn
homeassistant/components/sonos/* @amelchio
homeassistant/components/spaceapi/* @fabaff homeassistant/components/spaceapi/* @fabaff
homeassistant/components/speedtestdotnet/* @rohankapoorcom homeassistant/components/speedtestdotnet/* @rohankapoorcom
homeassistant/components/spider/* @peternijssen homeassistant/components/spider/* @peternijssen
@ -456,7 +459,6 @@ homeassistant/components/withings/* @vangorra
homeassistant/components/wled/* @frenck homeassistant/components/wled/* @frenck
homeassistant/components/workday/* @fabaff homeassistant/components/workday/* @fabaff
homeassistant/components/worldclock/* @fabaff homeassistant/components/worldclock/* @fabaff
homeassistant/components/wwlln/* @bachya
homeassistant/components/xbox_live/* @MartinHjelmare homeassistant/components/xbox_live/* @MartinHjelmare
homeassistant/components/xfinity/* @cisasteelersfan homeassistant/components/xfinity/* @cisasteelersfan
homeassistant/components/xiaomi_aqara/* @danielhiversen @syssi homeassistant/components/xiaomi_aqara/* @danielhiversen @syssi

View File

@ -2,79 +2,139 @@
## Our Pledge ## Our Pledge
In the interest of fostering an open and welcoming environment, we as We as members, contributors, and leaders pledge to make participation in our
contributors and maintainers pledge to making participation in our project and community a harassment-free experience for everyone, regardless of age, body
our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender
size, disability, ethnicity, gender identity and expression, level of experience, identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity and nationality, personal appearance, race, religion, or sexual identity
orientation. and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards ## Our Standards
Examples of behavior that contributes to creating a positive environment Examples of behavior that contributes to a positive environment for our
include: community include:
* Using welcoming and inclusive language * Demonstrating empathy and kindness toward other people
* Being respectful of differing viewpoints and experiences * Being respectful of differing opinions, viewpoints, and experiences
* Gracefully accepting constructive criticism * Giving and gracefully accepting constructive feedback
* Focusing on what is best for the community * Accepting responsibility and apologizing to those affected by our mistakes,
* Showing empathy towards other community members and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior by participants include: Examples of unacceptable behavior include:
* The use of sexualized language or imagery and unwelcome sexual attention or * The use of sexualized language or imagery, and sexual attention or
advances advances of any kind
* Trolling, insulting/derogatory comments, and personal or political attacks * Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment * Public or private harassment
* Publishing others' private information, such as a physical or electronic * Publishing others' private information, such as a physical or email
address, without explicit permission address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a * Other conduct which could reasonably be considered inappropriate in a
professional setting professional setting
## Our Responsibilities ## Enforcement Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable Community leaders are responsible for clarifying and enforcing our standards of
behavior and are expected to take appropriate and fair corrective action in acceptable behavior and will take appropriate and fair corrective action in
response to any instances of unacceptable behavior. response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Project maintainers have the right and responsibility to remove, edit, or Community leaders have the right and responsibility to remove, edit, or reject
reject comments, commits, code, wiki edits, issues, and other contributions comments, commits, code, wiki edits, issues, and other contributions that are
that are not aligned to this Code of Conduct, or to ban temporarily or not aligned to this Code of Conduct, and will communicate reasons for moderation
permanently any contributor for other behaviors that they deem inappropriate, decisions when appropriate.
threatening, offensive, or harmful.
## Scope ## Scope
This Code of Conduct applies both within project spaces and in public spaces This Code of Conduct applies within all community spaces, and also applies when
when an individual is representing the project or its community. Examples of an individual is officially representing the community in public spaces.
representing a project or community include using an official project e-mail Examples of representing our community include using an official e-mail address,
address, posting via an official social media account, or acting as an appointed posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be representative at an online or offline event.
further defined and clarified by project maintainers.
## Enforcement ## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [safety@home-assistant.io][email]. All reported to the community leaders responsible for enforcement at
complaints will be reviewed and investigated and will result in a response that [safety@home-assistant.io][email] or by using the report/flag feature of
is deemed necessary and appropriate to the circumstances. The project team is the medium used. All complaints will be reviewed and investigated promptly and
obligated to maintain confidentiality with regard to the reporter of an incident. fairly.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good All community leaders are obligated to respect the privacy and security of the
faith may face temporary or permanent repercussions as determined by other reporter of any incident.
members of the project's leadership.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution ## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, This Code of Conduct is adapted from the [Contributor Covenant][homepage],
available [here][version]. version 2.0, available [here][version].
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder][mozilla].
## Adoption ## Adoption
This Code of Conduct was first adopted January 21st, 2017 and announced in [this][coc-blog] blog post. This Code of Conduct was first adopted January 21st, 2017 and announced in
[this][coc-blog] blog post and has been updated on May 25th, 2020 to version
2.0 of the [Contributor Covenant][homepage] as announced in [this][coc2-blog]
blog post.
[homepage]: http://contributor-covenant.org For answers to common questions about this code of conduct, see the FAQ at
[version]: http://contributor-covenant.org/version/1/4/ <https://www.contributor-covenant.org/faq>. Translations are available at
<https://www.contributor-covenant.org/translations>.
[coc-blog]: /blog/2017/01/21/home-assistant-governance/
[coc2-blog]: /blog/2020/05/25/code-of-conduct-updated/
[email]: mailto:safety@home-assistant.io [email]: mailto:safety@home-assistant.io
[coc-blog]: https://home-assistant.io/blog/2017/01/21/home-assistant-governance/ [homepage]: http://contributor-covenant.org
[mozilla]: https://github.com/mozilla/diversity
[version]: https://www.contributor-covenant.org/version/2/0/code_of_conduct.html

View File

@ -1,4 +1,4 @@
FROM python:3.8 FROM mcr.microsoft.com/vscode/devcontainers/python:0-3.8
RUN \ RUN \
apt-get update && apt-get install -y --no-install-recommends \ apt-get update && apt-get install -y --no-install-recommends \

View File

@ -158,7 +158,7 @@ stages:
steps: steps:
- template: templates/azp-step-cache.yaml@azure - template: templates/azp-step-cache.yaml@azure
parameters: parameters:
keyfile: "requirements_test_all.txt | homeassistant/package_constraints.txt" keyfile: "requirements_test_all.txt | requirements_test.txt | homeassistant/package_constraints.txt"
build: | build: |
set -e set -e
python -m venv venv python -m venv venv

View File

@ -14,15 +14,14 @@ import voluptuous as vol
from homeassistant import config as conf_util, config_entries, core, loader from homeassistant import config as conf_util, config_entries, core, loader
from homeassistant.components import http from homeassistant.components import http
from homeassistant.const import ( from homeassistant.const import (
EVENT_HOMEASSISTANT_CLOSE,
EVENT_HOMEASSISTANT_STOP, EVENT_HOMEASSISTANT_STOP,
REQUIRED_NEXT_PYTHON_DATE, REQUIRED_NEXT_PYTHON_DATE,
REQUIRED_NEXT_PYTHON_VER, REQUIRED_NEXT_PYTHON_VER,
) )
from homeassistant.exceptions import HomeAssistantError from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
from homeassistant.setup import DATA_SETUP, async_setup_component from homeassistant.setup import DATA_SETUP, DATA_SETUP_STARTED, async_setup_component
from homeassistant.util.logging import AsyncHandler from homeassistant.util.logging import async_activate_log_queue_handler
from homeassistant.util.package import async_get_user_site, is_virtual_env from homeassistant.util.package import async_get_user_site, is_virtual_env
from homeassistant.util.yaml import clear_secret_cache from homeassistant.util.yaml import clear_secret_cache
@ -33,6 +32,8 @@ ERROR_LOG_FILENAME = "home-assistant.log"
# hass.data key for logging information. # hass.data key for logging information.
DATA_LOGGING = "logging" DATA_LOGGING = "logging"
LOG_SLOW_STARTUP_INTERVAL = 60
DEBUGGER_INTEGRATIONS = {"ptvsd"} DEBUGGER_INTEGRATIONS = {"ptvsd"}
CORE_INTEGRATIONS = ("homeassistant", "persistent_notification") CORE_INTEGRATIONS = ("homeassistant", "persistent_notification")
LOGGING_INTEGRATIONS = {"logger", "system_log", "sentry"} LOGGING_INTEGRATIONS = {"logger", "system_log", "sentry"}
@ -43,6 +44,13 @@ STAGE_1_INTEGRATIONS = {
"mqtt_eventstream", "mqtt_eventstream",
# To provide account link implementations # To provide account link implementations
"cloud", "cloud",
# Ensure supervisor is available
"hassio",
# Get the frontend up and running as soon
# as possible so problem integrations can
# be removed
"frontend",
"config",
} }
@ -278,24 +286,17 @@ def async_enable_logging(
err_handler.setLevel(logging.INFO if verbose else logging.WARNING) err_handler.setLevel(logging.INFO if verbose else logging.WARNING)
err_handler.setFormatter(logging.Formatter(fmt, datefmt=datefmt)) err_handler.setFormatter(logging.Formatter(fmt, datefmt=datefmt))
async_handler = AsyncHandler(hass.loop, err_handler)
async def async_stop_async_handler(_: Any) -> None:
"""Cleanup async handler."""
logging.getLogger("").removeHandler(async_handler) # type: ignore
await async_handler.async_close(blocking=True)
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_CLOSE, async_stop_async_handler)
logger = logging.getLogger("") logger = logging.getLogger("")
logger.addHandler(async_handler) # type: ignore logger.addHandler(err_handler)
logger.setLevel(logging.INFO) logger.setLevel(logging.INFO if verbose else logging.WARNING)
# Save the log file location for access by other components. # Save the log file location for access by other components.
hass.data[DATA_LOGGING] = err_log_path hass.data[DATA_LOGGING] = err_log_path
else: else:
_LOGGER.error("Unable to set up error log %s (access denied)", err_log_path) _LOGGER.error("Unable to set up error log %s (access denied)", err_log_path)
async_activate_log_queue_handler(hass)
async def async_mount_local_lib_path(config_dir: str) -> str: async def async_mount_local_lib_path(config_dir: str) -> str:
"""Add local library to Python Path. """Add local library to Python Path.
@ -331,13 +332,30 @@ async def _async_set_up_integrations(
) -> None: ) -> None:
"""Set up all the integrations.""" """Set up all the integrations."""
setup_started = hass.data[DATA_SETUP_STARTED] = {}
async def async_setup_multi_components(domains: Set[str]) -> None: async def async_setup_multi_components(domains: Set[str]) -> None:
"""Set up multiple domains. Log on failure.""" """Set up multiple domains. Log on failure."""
async def _async_log_pending_setups() -> None:
"""Periodic log of setups that are pending for longer than LOG_SLOW_STARTUP_INTERVAL."""
while True:
await asyncio.sleep(LOG_SLOW_STARTUP_INTERVAL)
remaining = [domain for domain in domains if domain in setup_started]
if remaining:
_LOGGER.info(
"Waiting on integrations to complete setup: %s",
", ".join(remaining),
)
futures = { futures = {
domain: hass.async_create_task(async_setup_component(hass, domain, config)) domain: hass.async_create_task(async_setup_component(hass, domain, config))
for domain in domains for domain in domains
} }
log_task = asyncio.create_task(_async_log_pending_setups())
await asyncio.wait(futures.values()) await asyncio.wait(futures.values())
log_task.cancel()
errors = [domain for domain in domains if futures[domain].exception()] errors = [domain for domain in domains if futures[domain].exception()]
for domain in errors: for domain in errors:
exception = futures[domain].exception() exception = futures[domain].exception()
@ -388,6 +406,8 @@ async def _async_set_up_integrations(
) )
if stage_1_domains: if stage_1_domains:
_LOGGER.info("Setting up %s", stage_1_domains)
await async_setup_multi_components(stage_1_domains) await async_setup_multi_components(stage_1_domains)
# Load all integrations # Load all integrations
@ -430,4 +450,5 @@ async def _async_set_up_integrations(
await async_setup_multi_components(stage_2_domains) await async_setup_multi_components(stage_2_domains)
# Wrap up startup # Wrap up startup
_LOGGER.debug("Waiting for startup to wrap up")
await hass.async_block_till_done() await hass.async_block_till_done()

View File

@ -12,7 +12,7 @@
"user": { "user": {
"data": { "data": {
"password": "Jelsz\u00f3", "password": "Jelsz\u00f3",
"username": "Email c\u00edm" "username": "E-mail"
}, },
"title": "T\u00f6ltse ki az Abode bejelentkez\u00e9si adatait" "title": "T\u00f6ltse ki az Abode bejelentkez\u00e9si adatait"
} }

View File

@ -12,7 +12,7 @@
"user": { "user": {
"data": { "data": {
"password": "Password", "password": "Password",
"username": "Indirizzo email" "username": "E-mail"
}, },
"title": "Inserisci le tue informazioni di accesso Abode" "title": "Inserisci le tue informazioni di accesso Abode"
} }

View File

@ -11,8 +11,8 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"password": "[%key_id:common::config_flow::data::password%]", "password": "Has\u0142o",
"username": "[%key_id:common::config_flow::data::email%]" "username": "Adres e-mail"
}, },
"title": "Wprowad\u017a informacje logowania Abode" "title": "Wprowad\u017a informacje logowania Abode"
} }

View File

@ -0,0 +1,59 @@
"""The Rollease Acmeda Automate integration."""
import asyncio
from homeassistant import config_entries, core
from .const import DOMAIN
from .hub import PulseHub
CONF_HUBS = "hubs"
PLATFORMS = ["cover", "sensor"]
async def async_setup(hass: core.HomeAssistant, config: dict):
"""Set up the Rollease Acmeda Automate component."""
return True
async def async_setup_entry(
hass: core.HomeAssistant, config_entry: config_entries.ConfigEntry
):
"""Set up Rollease Acmeda Automate hub from a config entry."""
hub = PulseHub(hass, config_entry)
if not await hub.async_setup():
return False
hass.data.setdefault(DOMAIN, {})
hass.data[DOMAIN][config_entry.entry_id] = hub
for component in PLATFORMS:
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry, component)
)
return True
async def async_unload_entry(
hass: core.HomeAssistant, config_entry: config_entries.ConfigEntry
):
"""Unload a config entry."""
hub = hass.data[DOMAIN][config_entry.entry_id]
unload_ok = all(
await asyncio.gather(
*[
hass.config_entries.async_forward_entry_unload(config_entry, component)
for component in PLATFORMS
]
)
)
if not await hub.async_reset():
return False
if unload_ok:
hass.data[DOMAIN].pop(config_entry.entry_id)
return unload_ok

View File

@ -0,0 +1,89 @@
"""Base class for Acmeda Roller Blinds."""
import aiopulse
from homeassistant.core import callback
from homeassistant.helpers import entity
from homeassistant.helpers.device_registry import async_get_registry as get_dev_reg
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_registry import async_get_registry as get_ent_reg
from .const import ACMEDA_ENTITY_REMOVE, DOMAIN, LOGGER
class AcmedaBase(entity.Entity):
"""Base representation of an Acmeda roller."""
def __init__(self, roller: aiopulse.Roller):
"""Initialize the roller."""
self.roller = roller
async def async_remove_and_unregister(self):
"""Unregister from entity and device registry and call entity remove function."""
LOGGER.error("Removing %s %s", self.__class__.__name__, self.unique_id)
ent_registry = await get_ent_reg(self.hass)
if self.entity_id in ent_registry.entities:
ent_registry.async_remove(self.entity_id)
dev_registry = await get_dev_reg(self.hass)
device = dev_registry.async_get_device(
identifiers={(DOMAIN, self.unique_id)}, connections=set()
)
if device is not None:
dev_registry.async_update_device(
device.id, remove_config_entry_id=self.registry_entry.config_entry_id
)
await self.async_remove()
async def async_added_to_hass(self):
"""Entity has been added to hass."""
self.roller.callback_subscribe(self.notify_update)
self.async_on_remove(
async_dispatcher_connect(
self.hass,
ACMEDA_ENTITY_REMOVE.format(self.roller.id),
self.async_remove_and_unregister,
)
)
async def async_will_remove_from_hass(self):
"""Entity being removed from hass."""
self.roller.callback_unsubscribe(self.notify_update)
@callback
def notify_update(self):
"""Write updated device state information."""
LOGGER.debug("Device update notification received: %s", self.name)
self.async_write_ha_state()
@property
def should_poll(self):
"""Report that Acmeda entities do not need polling."""
return False
@property
def unique_id(self):
"""Return the unique ID of this roller."""
return self.roller.id
@property
def device_id(self):
"""Return the ID of this roller."""
return self.roller.id
@property
def name(self):
"""Return the name of roller."""
return self.roller.name
@property
def device_info(self):
"""Return the device info."""
return {
"identifiers": {(DOMAIN, self.unique_id)},
"name": self.roller.name,
"manufacturer": "Rollease Acmeda",
"via_device": (DOMAIN, self.roller.hub.id),
}

View File

@ -0,0 +1,71 @@
"""Config flow for Rollease Acmeda Automate Pulse Hub."""
import asyncio
from typing import Dict, Optional
import aiopulse
import async_timeout
import voluptuous as vol
from homeassistant import config_entries
from .const import DOMAIN # pylint: disable=unused-import
class AcmedaFlowHandler(config_entries.ConfigFlow, domain=DOMAIN):
"""Handle a Acmeda config flow."""
VERSION = 1
CONNECTION_CLASS = config_entries.CONN_CLASS_LOCAL_POLL
def __init__(self):
"""Initialize the config flow."""
self.discovered_hubs: Optional[Dict[str, aiopulse.Hub]] = None
async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
if (
user_input is not None
and self.discovered_hubs is not None
# pylint: disable=unsupported-membership-test
and user_input["id"] in self.discovered_hubs
):
# pylint: disable=unsubscriptable-object
return await self.async_create(self.discovered_hubs[user_input["id"]])
# Already configured hosts
already_configured = {
entry.unique_id for entry in self._async_current_entries()
}
hubs = []
try:
with async_timeout.timeout(5):
async for hub in aiopulse.Hub.discover():
if hub.id not in already_configured:
hubs.append(hub)
except asyncio.TimeoutError:
pass
if len(hubs) == 0:
return self.async_abort(reason="all_configured")
if len(hubs) == 1:
return await self.async_create(hubs[0])
self.discovered_hubs = {hub.id: hub for hub in hubs}
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required("id"): vol.In(
{hub.id: f"{hub.id} {hub.host}" for hub in hubs}
)
}
),
)
async def async_create(self, hub):
"""Create the Acmeda Hub entry."""
await self.async_set_unique_id(hub.id, raise_on_progress=False)
return self.async_create_entry(title=hub.id, data={"host": hub.host})

View File

@ -0,0 +1,8 @@
"""Constants for the Rollease Acmeda Automate integration."""
import logging
LOGGER = logging.getLogger(__package__)
DOMAIN = "acmeda"
ACMEDA_HUB_UPDATE = "acmeda_hub_update_{}"
ACMEDA_ENTITY_REMOVE = "acmeda_entity_remove_{}"

View File

@ -0,0 +1,122 @@
"""Support for Acmeda Roller Blinds."""
from homeassistant.components.cover import (
ATTR_POSITION,
SUPPORT_CLOSE,
SUPPORT_CLOSE_TILT,
SUPPORT_OPEN,
SUPPORT_OPEN_TILT,
SUPPORT_SET_POSITION,
SUPPORT_SET_TILT_POSITION,
SUPPORT_STOP,
SUPPORT_STOP_TILT,
CoverEntity,
)
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from .base import AcmedaBase
from .const import ACMEDA_HUB_UPDATE, DOMAIN
from .helpers import async_add_acmeda_entities
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the Acmeda Rollers from a config entry."""
hub = hass.data[DOMAIN][config_entry.entry_id]
current = set()
@callback
def async_add_acmeda_covers():
async_add_acmeda_entities(
hass, AcmedaCover, config_entry, current, async_add_entities
)
hub.cleanup_callbacks.append(
async_dispatcher_connect(
hass,
ACMEDA_HUB_UPDATE.format(config_entry.entry_id),
async_add_acmeda_covers,
)
)
class AcmedaCover(AcmedaBase, CoverEntity):
"""Representation of a Acmeda cover device."""
@property
def current_cover_position(self):
"""Return the current position of the roller blind.
None is unknown, 0 is closed, 100 is fully open.
"""
position = None
if self.roller.type != 7:
position = 100 - self.roller.closed_percent
return position
@property
def current_cover_tilt_position(self):
"""Return the current tilt of the roller blind.
None is unknown, 0 is closed, 100 is fully open.
"""
position = None
if self.roller.type == 7 or self.roller.type == 10:
position = 100 - self.roller.closed_percent
return position
@property
def supported_features(self):
"""Flag supported features."""
supported_features = 0
if self.current_cover_position is not None:
supported_features |= (
SUPPORT_OPEN | SUPPORT_CLOSE | SUPPORT_STOP | SUPPORT_SET_POSITION
)
if self.current_cover_tilt_position is not None:
supported_features |= (
SUPPORT_OPEN_TILT
| SUPPORT_CLOSE_TILT
| SUPPORT_STOP_TILT
| SUPPORT_SET_TILT_POSITION
)
return supported_features
@property
def is_closed(self):
"""Return if the cover is closed."""
is_closed = self.roller.closed_percent == 100
return is_closed
async def close_cover(self, **kwargs):
"""Close the roller."""
await self.roller.move_down()
async def open_cover(self, **kwargs):
"""Open the roller."""
await self.roller.move_up()
async def stop_cover(self, **kwargs):
"""Stop the roller."""
await self.roller.move_stop()
async def set_cover_position(self, **kwargs):
"""Move the roller shutter to a specific position."""
await self.roller.move_to(100 - kwargs[ATTR_POSITION])
async def close_cover_tilt(self, **kwargs):
"""Close the roller."""
await self.roller.move_down()
async def open_cover_tilt(self, **kwargs):
"""Open the roller."""
await self.roller.move_up()
async def stop_cover_tilt(self, **kwargs):
"""Stop the roller."""
await self.roller.move_stop()
async def set_cover_tilt(self, **kwargs):
"""Tilt the roller shutter to a specific position."""
await self.roller.move_to(100 - kwargs[ATTR_POSITION])

View File

@ -0,0 +1,10 @@
"""Errors for the Acmeda Pulse component."""
from homeassistant.exceptions import HomeAssistantError
class PulseException(HomeAssistantError):
"""Base class for Acmeda Pulse exceptions."""
class CannotConnect(PulseException):
"""Unable to connect to the bridge."""

View File

@ -0,0 +1,41 @@
"""Helper functions for Acmeda Pulse."""
from homeassistant.core import callback
from homeassistant.helpers.device_registry import async_get_registry as get_dev_reg
from .const import DOMAIN, LOGGER
@callback
def async_add_acmeda_entities(
hass, entity_class, config_entry, current, async_add_entities
):
"""Add any new entities."""
hub = hass.data[DOMAIN][config_entry.entry_id]
LOGGER.debug("Looking for new %s on: %s", entity_class.__name__, hub.host)
api = hub.api.rollers
new_items = []
for unique_id, roller in api.items():
if unique_id not in current:
LOGGER.debug("New %s %s", entity_class.__name__, unique_id)
new_item = entity_class(roller)
current.add(unique_id)
new_items.append(new_item)
async_add_entities(new_items)
async def update_devices(hass, config_entry, api):
"""Tell hass that device info has been updated."""
dev_registry = await get_dev_reg(hass)
for api_item in api.values():
# Update Device name
device = dev_registry.async_get_device(
identifiers={(DOMAIN, api_item.id)}, connections=set()
)
if device is not None:
dev_registry.async_update_device(
device.id, name=api_item.name,
)

View File

@ -0,0 +1,88 @@
"""Code to handle a Pulse Hub."""
import asyncio
from typing import Optional
import aiopulse
from homeassistant.helpers.dispatcher import async_dispatcher_send
from .const import ACMEDA_ENTITY_REMOVE, ACMEDA_HUB_UPDATE, LOGGER
from .helpers import update_devices
class PulseHub:
"""Manages a single Pulse Hub."""
def __init__(self, hass, config_entry):
"""Initialize the system."""
self.config_entry = config_entry
self.hass = hass
self.api: Optional[aiopulse.Hub] = None
self.tasks = []
self.current_rollers = {}
self.cleanup_callbacks = []
@property
def title(self):
"""Return the title of the hub shown in the integrations list."""
return f"{self.api.id} ({self.api.host})"
@property
def host(self):
"""Return the host of this hub."""
return self.config_entry.data["host"]
async def async_setup(self, tries=0):
"""Set up a hub based on host parameter."""
host = self.host
hub = aiopulse.Hub(host)
self.api = hub
hub.callback_subscribe(self.async_notify_update)
self.tasks.append(asyncio.create_task(hub.run()))
LOGGER.debug("Hub setup complete")
return True
async def async_reset(self):
"""Reset this hub to default state."""
for cleanup_callback in self.cleanup_callbacks:
cleanup_callback()
# If not setup
if self.api is None:
return False
self.api.callback_unsubscribe(self.async_notify_update)
await self.api.stop()
del self.api
self.api = None
# Wait for any running tasks to complete
await asyncio.wait(self.tasks)
return True
async def async_notify_update(self, update_type):
"""Evaluate entities when hub reports that update has occurred."""
LOGGER.debug("Hub {update_type.name} updated")
if update_type == aiopulse.UpdateType.rollers:
await update_devices(self.hass, self.config_entry, self.api.rollers)
self.hass.config_entries.async_update_entry(
self.config_entry, title=self.title
)
async_dispatcher_send(
self.hass, ACMEDA_HUB_UPDATE.format(self.config_entry.entry_id)
)
for unique_id in list(self.current_rollers):
if unique_id not in self.api.rollers:
LOGGER.debug("Notifying remove of %s", unique_id)
self.current_rollers.pop(unique_id)
async_dispatcher_send(
self.hass, ACMEDA_ENTITY_REMOVE.format(unique_id)
)

View File

@ -0,0 +1,10 @@
{
"domain": "acmeda",
"name": "Rollease Acmeda Automate",
"config_flow": true,
"documentation": "https://www.home-assistant.io/integrations/acmeda",
"requirements": ["aiopulse==0.4.0"],
"codeowners": [
"@atmurray"
]
}

View File

@ -0,0 +1,46 @@
"""Support for Acmeda Roller Blind Batteries."""
from homeassistant.const import DEVICE_CLASS_BATTERY, UNIT_PERCENTAGE
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from .base import AcmedaBase
from .const import ACMEDA_HUB_UPDATE, DOMAIN
from .helpers import async_add_acmeda_entities
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up the Acmeda Rollers from a config entry."""
hub = hass.data[DOMAIN][config_entry.entry_id]
current = set()
@callback
def async_add_acmeda_sensors():
async_add_acmeda_entities(
hass, AcmedaBattery, config_entry, current, async_add_entities
)
hub.cleanup_callbacks.append(
async_dispatcher_connect(
hass,
ACMEDA_HUB_UPDATE.format(config_entry.entry_id),
async_add_acmeda_sensors,
)
)
class AcmedaBattery(AcmedaBase):
"""Representation of a Acmeda cover device."""
device_class = DEVICE_CLASS_BATTERY
unit_of_measurement = UNIT_PERCENTAGE
@property
def name(self):
"""Return the name of roller."""
return f"{super().name} Battery"
@property
def state(self):
"""Return the state of the device."""
return self.roller.battery

View File

@ -0,0 +1,16 @@
{
"title": "Rollease Acmeda Automate",
"config": {
"step": {
"user": {
"title": "Pick a hub to add",
"data": {
"id": "Host ID"
}
}
},
"abort": {
"all_configured": "No new Pulse hubs discovered."
}
}
}

View File

@ -0,0 +1,16 @@
{
"config": {
"abort": {
"all_configured": "No s'han descobert nous hubs de Pulse."
},
"step": {
"user": {
"data": {
"id": "ID d'amfitri\u00f3"
},
"title": "Selecci\u00f3 del Hub a afegir"
}
}
},
"title": "Rollease Acmeda Automate"
}

View File

@ -3,8 +3,7 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"latitude": "Latitude", "id": "Host-ID"
"longitude": "Longitude"
} }
} }
} }

View File

@ -0,0 +1,16 @@
{
"config": {
"abort": {
"all_configured": "No new Pulse hubs discovered."
},
"step": {
"user": {
"data": {
"id": "Host ID"
},
"title": "Pick a hub to add"
}
}
},
"title": "Rollease Acmeda Automate"
}

View File

@ -0,0 +1,16 @@
{
"config": {
"abort": {
"all_configured": "No se han descubierto nuevos hubs Pulse."
},
"step": {
"user": {
"data": {
"id": "ID de host"
},
"title": "Elige un hub para a\u00f1adir"
}
}
},
"title": "Rollease Acmeda Automate"
}

View File

@ -0,0 +1,12 @@
{
"config": {
"step": {
"user": {
"data": {
"id": "ID de l'h\u00f4te"
},
"title": "Choisissez un hub \u00e0 ajouter"
}
}
}
}

View File

@ -0,0 +1,16 @@
{
"config": {
"abort": {
"all_configured": "Non sono stati scoperti nuovi hub Pulse."
},
"step": {
"user": {
"data": {
"id": "ID host"
},
"title": "Scegliere un hub da aggiungere"
}
}
},
"title": "Rollease Acmeda Automate"
}

View File

@ -0,0 +1,16 @@
{
"config": {
"abort": {
"all_configured": "\ubc1c\uacac\ub41c \uc0c8\ub85c\uc6b4 Pulse \ud5c8\ube0c\uac00 \uc5c6\uc2b5\ub2c8\ub2e4."
},
"step": {
"user": {
"data": {
"id": "\ud638\uc2a4\ud2b8 ID"
},
"title": "\ucd94\uac00\ud560 \ud5c8\ube0c \uc120\ud0dd\ud558\uae30"
}
}
},
"title": "Rollease Acmeda Automate"
}

View File

@ -0,0 +1,16 @@
{
"config": {
"abort": {
"all_configured": "Keng nei Pulse Hubs entdeckt."
},
"step": {
"user": {
"data": {
"id": "Host ID"
},
"title": "Wiel den Hub aus dee soll dob\u00e4igesat ginn."
}
}
},
"title": "Rollease ACmeda Automate"
}

View File

@ -0,0 +1,16 @@
{
"config": {
"abort": {
"all_configured": "Geen nieuwe Pulse hubs ontdekt."
},
"step": {
"user": {
"data": {
"id": "Host ID"
},
"title": "Kies een hub om toe te voegen"
}
}
},
"title": "Rollease Acmeda Automate"
}

View File

@ -0,0 +1,16 @@
{
"config": {
"abort": {
"all_configured": "Ingen nye Pulse-hub oppdaget."
},
"step": {
"user": {
"data": {
"id": "Verts-ID"
},
"title": "Velg en hub du vil legge til"
}
}
},
"title": ""
}

View File

@ -0,0 +1,16 @@
{
"config": {
"abort": {
"all_configured": "Nie wykryto hub\u00f3w Pulse."
},
"step": {
"user": {
"data": {
"id": "ID hosta"
},
"title": "Wybierz hub, kt\u00f3ry chcesz doda\u0107"
}
}
},
"title": "Rollease Acmeda Automate"
}

View File

@ -0,0 +1,16 @@
{
"config": {
"abort": {
"all_configured": "\u0423\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430 \u043d\u0435 \u043e\u0431\u043d\u0430\u0440\u0443\u0436\u0435\u043d\u044b."
},
"step": {
"user": {
"data": {
"id": "ID \u0445\u043e\u0441\u0442\u0430"
},
"title": "\u0412\u044b\u0431\u0435\u0440\u0438\u0442\u0435 \u0445\u0430\u0431, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0443\u0436\u043d\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c"
}
}
},
"title": "Rollease Acmeda Automate"
}

View File

@ -0,0 +1,16 @@
{
"config": {
"abort": {
"all_configured": "\u672a\u641c\u5c0b\u5230 Pulse hub"
},
"step": {
"user": {
"data": {
"id": "\u4e3b\u6a5f ID"
},
"title": "\u9078\u64c7\u6240\u8981\u65b0\u589e\u7684 Hub"
}
}
},
"title": "Rollease Acmeda Automate"
}

View File

@ -21,8 +21,7 @@
"username": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u043e \u0438\u043c\u0435", "username": "\u041f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u0441\u043a\u043e \u0438\u043c\u0435",
"verify_ssl": "AdGuard Home \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u043d\u0430\u0434\u0435\u0436\u0434\u0435\u043d \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442" "verify_ssl": "AdGuard Home \u0438\u0437\u043f\u043e\u043b\u0437\u0432\u0430 \u043d\u0430\u0434\u0435\u0436\u0434\u0435\u043d \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442"
}, },
"description": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0412\u0430\u0448\u0438\u044f AdGuard Home, \u0437\u0430 \u0434\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0435 \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u0435 \u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b.", "description": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 \u0412\u0430\u0448\u0438\u044f AdGuard Home, \u0437\u0430 \u0434\u0430 \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442\u0435 \u043d\u0430\u0431\u043b\u044e\u0434\u0435\u043d\u0438\u0435 \u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b."
"title": "\u0421\u0432\u044a\u0440\u0436\u0435\u0442\u0435 \u0412\u0430\u0448\u0438\u044f AdGuard Home."
} }
} }
} }

View File

@ -23,8 +23,7 @@
"username": "[%key::common::config_flow::data::username%]", "username": "[%key::common::config_flow::data::username%]",
"verify_ssl": "AdGuard Home utilitza un certificat adequat" "verify_ssl": "AdGuard Home utilitza un certificat adequat"
}, },
"description": "Configuraci\u00f3 de la inst\u00e0ncia d'AdGuard Home, permet el control i la monitoritzaci\u00f3.", "description": "Configuraci\u00f3 de la inst\u00e0ncia d'AdGuard Home, permet el control i la monitoritzaci\u00f3."
"title": "Enlla\u00e7ar AdGuard Home."
} }
} }
} }

View File

@ -21,8 +21,7 @@
"username": "Brugernavn", "username": "Brugernavn",
"verify_ssl": "AdGuard Home bruger et korrekt certifikat" "verify_ssl": "AdGuard Home bruger et korrekt certifikat"
}, },
"description": "Konfigurer din AdGuard Home-instans for at tillade overv\u00e5gning og kontrol.", "description": "Konfigurer din AdGuard Home-instans for at tillade overv\u00e5gning og kontrol."
"title": "Forbind din AdGuard Home."
} }
} }
} }

View File

@ -23,8 +23,7 @@
"username": "Benutzername", "username": "Benutzername",
"verify_ssl": "AdGuard Home verwendet ein richtiges Zertifikat" "verify_ssl": "AdGuard Home verwendet ein richtiges Zertifikat"
}, },
"description": "Richte deine AdGuard Home-Instanz ein um sie zu \u00dcberwachen und zu Steuern.", "description": "Richte deine AdGuard Home-Instanz ein um sie zu \u00dcberwachen und zu Steuern."
"title": "Verkn\u00fcpfe AdGuard Home."
} }
} }
} }

View File

@ -23,8 +23,7 @@
"username": "Username", "username": "Username",
"verify_ssl": "AdGuard Home uses a proper certificate" "verify_ssl": "AdGuard Home uses a proper certificate"
}, },
"description": "Set up your AdGuard Home instance to allow monitoring and control.", "description": "Set up your AdGuard Home instance to allow monitoring and control."
"title": "Link your AdGuard Home."
} }
} }
} }

View File

@ -16,13 +16,14 @@
}, },
"user": { "user": {
"data": { "data": {
"host": "Host",
"password": "Contrase\u00f1a", "password": "Contrase\u00f1a",
"port": "Puerto",
"ssl": "AdGuard Home utiliza un certificado SSL", "ssl": "AdGuard Home utiliza un certificado SSL",
"username": "Nombre de usuario", "username": "Nombre de usuario",
"verify_ssl": "AdGuard Home utiliza un certificado adecuado" "verify_ssl": "AdGuard Home utiliza un certificado adecuado"
}, },
"description": "Configure su instancia de AdGuard Home para permitir la supervisi\u00f3n y el control.", "description": "Configure su instancia de AdGuard Home para permitir la supervisi\u00f3n y el control."
"title": "Enlace su AdGuard Home."
} }
} }
} }

View File

@ -23,8 +23,7 @@
"username": "Usuario", "username": "Usuario",
"verify_ssl": "AdGuard Home utiliza un certificado apropiado" "verify_ssl": "AdGuard Home utiliza un certificado apropiado"
}, },
"description": "Configure su instancia de AdGuard Home para permitir la supervisi\u00f3n y el control.", "description": "Configure su instancia de AdGuard Home para permitir la supervisi\u00f3n y el control."
"title": "Enlace su AdGuard Home."
} }
} }
} }

View File

@ -23,8 +23,7 @@
"username": "Nom d'utilisateur", "username": "Nom d'utilisateur",
"verify_ssl": "AdGuard Home utilise un certificat appropri\u00e9" "verify_ssl": "AdGuard Home utilise un certificat appropri\u00e9"
}, },
"description": "Configurez votre instance AdGuard Home pour permettre la surveillance et le contr\u00f4le.", "description": "Configurez votre instance AdGuard Home pour permettre la surveillance et le contr\u00f4le."
"title": "Liez votre AdGuard Home."
} }
} }
} }

View File

@ -3,6 +3,7 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"host": "Hoszt",
"password": "Jelsz\u00f3", "password": "Jelsz\u00f3",
"port": "Port", "port": "Port",
"username": "Felhaszn\u00e1l\u00f3n\u00e9v" "username": "Felhaszn\u00e1l\u00f3n\u00e9v"

View File

@ -23,8 +23,7 @@
"username": "Nome utente", "username": "Nome utente",
"verify_ssl": "AdGuard Home utilizza un certificato appropriato" "verify_ssl": "AdGuard Home utilizza un certificato appropriato"
}, },
"description": "Configura l'istanza di AdGuard Home per consentire il monitoraggio e il controllo.", "description": "Configura l'istanza di AdGuard Home per consentire il monitoraggio e il controllo."
"title": "Collega la tua AdGuard Home."
} }
} }
} }

View File

@ -23,8 +23,7 @@
"username": "\uc0ac\uc6a9\uc790 \uc774\ub984", "username": "\uc0ac\uc6a9\uc790 \uc774\ub984",
"verify_ssl": "AdGuard Home \uc740 \uc62c\ubc14\ub978 \uc778\uc99d\uc11c\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4" "verify_ssl": "AdGuard Home \uc740 \uc62c\ubc14\ub978 \uc778\uc99d\uc11c\ub97c \uc0ac\uc6a9\ud558\uace0 \uc788\uc2b5\ub2c8\ub2e4"
}, },
"description": "\ubaa8\ub2c8\ud130\ub9c1 \ubc0f \uc81c\uc5b4\uac00 \uac00\ub2a5\ud558\ub3c4\ub85d AdGuard Home \uc778\uc2a4\ud134\uc2a4\ub97c \uc124\uc815\ud574\uc8fc\uc138\uc694.", "description": "\ubaa8\ub2c8\ud130\ub9c1 \ubc0f \uc81c\uc5b4\uac00 \uac00\ub2a5\ud558\ub3c4\ub85d AdGuard Home \uc778\uc2a4\ud134\uc2a4\ub97c \uc124\uc815\ud574\uc8fc\uc138\uc694."
"title": "AdGuard Home \uc5f0\uacb0\ud558\uae30"
} }
} }
} }

View File

@ -23,8 +23,7 @@
"username": "Benotzernumm", "username": "Benotzernumm",
"verify_ssl": "AdGuard Home benotzt een eegenen Zertifikat" "verify_ssl": "AdGuard Home benotzt een eegenen Zertifikat"
}, },
"description": "Konfigur\u00e9iert \u00e4r AdGuard Home Instanz fir d'Iwwerwaachung an d'Kontroll z'erlaben.", "description": "Konfigur\u00e9iert \u00e4r AdGuard Home Instanz fir d'Iwwerwaachung an d'Kontroll z'erlaben."
"title": "Verbannt \u00e4ren AdGuard Home"
} }
} }
} }

View File

@ -21,8 +21,7 @@
"username": "Gebruikersnaam", "username": "Gebruikersnaam",
"verify_ssl": "AdGuard Home maakt gebruik van een goed certificaat" "verify_ssl": "AdGuard Home maakt gebruik van een goed certificaat"
}, },
"description": "Stel uw AdGuard Home-instantie in om toezicht en controle mogelijk te maken.", "description": "Stel uw AdGuard Home-instantie in om toezicht en controle mogelijk te maken."
"title": "Link uw AdGuard Home."
} }
} }
} }

View File

@ -21,8 +21,7 @@
"ssl": "AdGuard Hjem bruker et SSL-sertifikat", "ssl": "AdGuard Hjem bruker et SSL-sertifikat",
"verify_ssl": "AdGuard Home bruker et riktig sertifikat" "verify_ssl": "AdGuard Home bruker et riktig sertifikat"
}, },
"description": "Sett opp din AdGuard Hjem instans for \u00e5 tillate overv\u00e5king og kontroll.", "description": "Sett opp din AdGuard Hjem instans for \u00e5 tillate overv\u00e5king og kontroll."
"title": "Koble til ditt AdGuard Hjem."
} }
} }
} }

View File

@ -7,7 +7,7 @@
"single_instance_allowed": "Dozwolona jest tylko jedna konfiguracja AdGuard Home." "single_instance_allowed": "Dozwolona jest tylko jedna konfiguracja AdGuard Home."
}, },
"error": { "error": {
"connection_error": "[%key_id:common::config_flow::error::cannot_connect%]" "connection_error": "Nie mo\u017cna nawi\u0105za\u0107 po\u0142\u0105czenia."
}, },
"step": { "step": {
"hassio_confirm": { "hassio_confirm": {
@ -16,15 +16,14 @@
}, },
"user": { "user": {
"data": { "data": {
"host": "[%key_id:common::config_flow::data::host%]", "host": "Nazwa hosta lub adres IP",
"password": "[%key_id:common::config_flow::data::password%]", "password": "Has\u0142o",
"port": "[%key_id:common::config_flow::data::port%]", "port": "Port",
"ssl": "AdGuard Home u\u017cywa certyfikatu SSL", "ssl": "AdGuard Home u\u017cywa certyfikatu SSL",
"username": "[%key_id:common::config_flow::data::username%]", "username": "Nazwa u\u017cytkownika",
"verify_ssl": "AdGuard Home u\u017cywa odpowiedniego certyfikatu." "verify_ssl": "AdGuard Home u\u017cywa odpowiedniego certyfikatu."
}, },
"description": "Skonfiguruj instancj\u0119 AdGuard Home, aby umo\u017cliwi\u0107 monitorowanie i kontrol\u0119.", "description": "Skonfiguruj instancj\u0119 AdGuard Home, aby umo\u017cliwi\u0107 monitorowanie i kontrol\u0119."
"title": "Po\u0142\u0105cz AdGuard Home"
} }
} }
} }

View File

@ -19,8 +19,7 @@
"username": "Nome de usu\u00e1rio", "username": "Nome de usu\u00e1rio",
"verify_ssl": "O AdGuard Home usa um certificado apropriado" "verify_ssl": "O AdGuard Home usa um certificado apropriado"
}, },
"description": "Configure sua inst\u00e2ncia do AdGuard Home para permitir o monitoramento e o controle.", "description": "Configure sua inst\u00e2ncia do AdGuard Home para permitir o monitoramento e o controle."
"title": "Vincule o seu AdGuard Home."
} }
} }
} }

View File

@ -23,8 +23,7 @@
"username": "\u041b\u043e\u0433\u0438\u043d", "username": "\u041b\u043e\u0433\u0438\u043d",
"verify_ssl": "AdGuard Home \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442" "verify_ssl": "AdGuard Home \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u044b\u0439 \u0441\u0435\u0440\u0442\u0438\u0444\u0438\u043a\u0430\u0442"
}, },
"description": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 Home Assistant \u0434\u043b\u044f \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430 \u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f AdGuard Home.", "description": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u0442\u0435 Home Assistant \u0434\u043b\u044f \u043c\u043e\u043d\u0438\u0442\u043e\u0440\u0438\u043d\u0433\u0430 \u0438 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f AdGuard Home."
"title": "AdGuard Home"
} }
} }
} }

View File

@ -23,8 +23,7 @@
"username": "Uporabni\u0161ko ime", "username": "Uporabni\u0161ko ime",
"verify_ssl": "AdGuard Home uporablja ustrezen certifikat" "verify_ssl": "AdGuard Home uporablja ustrezen certifikat"
}, },
"description": "Nastavite primerek AdGuard Home, da omogo\u010dite spremljanje in nadzor.", "description": "Nastavite primerek AdGuard Home, da omogo\u010dite spremljanje in nadzor."
"title": "Pove\u017eite svoj AdGuard Home."
} }
} }
} }

View File

@ -21,8 +21,7 @@
"username": "Anv\u00e4ndarnamn", "username": "Anv\u00e4ndarnamn",
"verify_ssl": "AdGuard Home anv\u00e4nder ett korrekt certifikat" "verify_ssl": "AdGuard Home anv\u00e4nder ett korrekt certifikat"
}, },
"description": "St\u00e4ll in din AdGuard Home-instans f\u00f6r att till\u00e5ta \u00f6vervakning och kontroll.", "description": "St\u00e4ll in din AdGuard Home-instans f\u00f6r att till\u00e5ta \u00f6vervakning och kontroll."
"title": "L\u00e4nka din AdGuard Home."
} }
} }
} }

View File

@ -23,8 +23,7 @@
"username": "\u4f7f\u7528\u8005\u540d\u7a31", "username": "\u4f7f\u7528\u8005\u540d\u7a31",
"verify_ssl": "AdGuard Home \u4f7f\u7528\u5c0d\u61c9\u8a8d\u8b49" "verify_ssl": "AdGuard Home \u4f7f\u7528\u5c0d\u61c9\u8a8d\u8b49"
}, },
"description": "\u8a2d\u5b9a AdGuard Home \u4ee5\u9032\u884c\u76e3\u63a7\u3002", "description": "\u8a2d\u5b9a AdGuard Home \u4ee5\u9032\u884c\u76e3\u63a7\u3002"
"title": "\u9023\u7d50 AdGuard Home\u3002"
} }
} }
} }

View File

@ -0,0 +1,21 @@
{
"config": {
"abort": {
"already_configured": "El dispositivo ya est\u00e1 configurado"
},
"error": {
"already_in_progress": "El flujo de configuraci\u00f3n para el dispositivo ya est\u00e1 en progreso.",
"device_unavailable": "El dispositivo no est\u00e1 disponible"
},
"step": {
"user": {
"data": {
"host": "Host",
"port": "Puerto"
},
"title": "Configurar Agent DVR"
}
}
},
"title": "Agent DVR"
}

View File

@ -12,7 +12,8 @@
"data": { "data": {
"host": "H\u00f4te", "host": "H\u00f4te",
"port": "Port" "port": "Port"
} },
"title": "Configurer l'agent DVR"
} }
} }
}, },

View File

@ -3,8 +3,8 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"latitude": "Leveysaste", "host": "Hoszt",
"longitude": "Pituusaste" "port": "Port"
} }
} }
} }

View File

@ -1,7 +1,7 @@
{ {
"config": { "config": {
"abort": { "abort": {
"already_configured": "[%key_id:common::config_flow::abort::already_configured_device%]" "already_configured": "Urz\u0105dzenie jest ju\u017c skonfigurowane."
}, },
"error": { "error": {
"already_in_progress": "Konfiguracja urz\u0105dzenia jest ju\u017c w toku.", "already_in_progress": "Konfiguracja urz\u0105dzenia jest ju\u017c w toku.",
@ -10,8 +10,8 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"host": "[%key_id:common::config_flow::data::host%]", "host": "Nazwa hosta lub adres IP",
"port": "[%key_id:common::config_flow::data::port%]" "port": "Port"
}, },
"title": "Konfiguracja Agent DVR" "title": "Konfiguracja Agent DVR"
} }

View File

@ -0,0 +1,7 @@
{
"config": {
"error": {
"device_unavailable": "O dispositivo n\u00e3o est\u00e1 dispon\u00edvel"
}
}
}

View File

@ -10,7 +10,7 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"api_key": "Clau API d'Airly", "api_key": "Clau API",
"latitude": "Latitud", "latitude": "Latitud",
"longitude": "Longitud", "longitude": "Longitud",
"name": "Nom de la integraci\u00f3" "name": "Nom de la integraci\u00f3"

View File

@ -10,7 +10,7 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"api_key": "Airly API kulcs", "api_key": "API kulcs",
"latitude": "Sz\u00e9less\u00e9g", "latitude": "Sz\u00e9less\u00e9g",
"longitude": "Hossz\u00fas\u00e1g", "longitude": "Hossz\u00fas\u00e1g",
"name": "Az integr\u00e1ci\u00f3 neve" "name": "Az integr\u00e1ci\u00f3 neve"

View File

@ -10,7 +10,7 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"api_key": "Chiave API Airly", "api_key": "Chiave API",
"latitude": "Latitudine", "latitude": "Latitudine",
"longitude": "Logitudine", "longitude": "Logitudine",
"name": "Nome dell'integrazione" "name": "Nome dell'integrazione"

View File

@ -10,7 +10,7 @@
"step": { "step": {
"user": { "user": {
"data": { "data": {
"api_key": "[%key_id:common::config_flow::data::api_key%] Airly", "api_key": "Klucz API",
"latitude": "Szeroko\u015b\u0107 geograficzna", "latitude": "Szeroko\u015b\u0107 geograficzna",
"longitude": "D\u0142ugo\u015b\u0107 geograficzna", "longitude": "D\u0142ugo\u015b\u0107 geograficzna",
"name": "Nazwa integracji" "name": "Nazwa integracji"

View File

@ -1,7 +1,7 @@
{ {
"config": { "config": {
"abort": { "abort": {
"already_configured": "Aquesta clau API ja est\u00e0 sent utilitzada." "already_configured": "Aquestes coordenades o Node/Pro ID ja estan registrades."
}, },
"error": { "error": {
"general_error": "S'ha produ\u00eft un error desconegut.", "general_error": "S'ha produ\u00eft un error desconegut.",
@ -21,21 +21,18 @@
"node_pro": { "node_pro": {
"data": { "data": {
"ip_address": "Adre\u00e7a IP o amfitri\u00f3 de la unitat", "ip_address": "Adre\u00e7a IP o amfitri\u00f3 de la unitat",
"password": "Contrasenya de la unitat" "password": "Contrasenya"
}, },
"description": "Monitoritza una unitat personal d'AirVisual. Pots obtenir la contrasenya des de la interf\u00edcie d'usuari (UI) de la unitat.", "description": "Monitoritza una unitat personal d'AirVisual. Pots obtenir la contrasenya des de la interf\u00edcie d'usuari (UI) de la unitat.",
"title": "Configuraci\u00f3 d'AirVisual Node/Pro" "title": "Configuraci\u00f3 d'AirVisual Node/Pro"
}, },
"user": { "user": {
"data": { "data": {
"api_key": "Clau API",
"cloud_api": "Ubicaci\u00f3 geogr\u00e0fica", "cloud_api": "Ubicaci\u00f3 geogr\u00e0fica",
"latitude": "Latitud",
"longitude": "Longitud",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "Tipus d'integraci\u00f3" "type": "Tipus d'integraci\u00f3"
}, },
"description": "Monitoritzaci\u00f3 de la qualitat de l'aire per ubicaci\u00f3 geogr\u00e0fica.", "description": "Tria quin tipus de dades d'AirVisual vols monitoritzar.",
"title": "Configura AirVisual" "title": "Configura AirVisual"
} }
} }
@ -46,7 +43,6 @@
"data": { "data": {
"show_on_map": "Mostra al mapa l'\u00e0rea geogr\u00e0fica monitoritzada" "show_on_map": "Mostra al mapa l'\u00e0rea geogr\u00e0fica monitoritzada"
}, },
"description": "Estableix les diferents opcions de la integraci\u00f3 AirVisual.",
"title": "Configuraci\u00f3 d'AirVisual" "title": "Configuraci\u00f3 d'AirVisual"
} }
} }

View File

@ -27,10 +27,7 @@
}, },
"user": { "user": {
"data": { "data": {
"api_key": "API-Schl\u00fcssel",
"cloud_api": "Geografische Position", "cloud_api": "Geografische Position",
"latitude": "Breitengrad",
"longitude": "L\u00e4ngengrad",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "Integrationstyp" "type": "Integrationstyp"
}, },
@ -45,7 +42,6 @@
"data": { "data": {
"show_on_map": "Zeigen Sie die \u00fcberwachte Geografie auf der Karte an" "show_on_map": "Zeigen Sie die \u00fcberwachte Geografie auf der Karte an"
}, },
"description": "Legen Sie verschiedene Optionen f\u00fcr die AirVisual-Integration fest.",
"title": "Konfigurieren Sie AirVisual" "title": "Konfigurieren Sie AirVisual"
} }
} }

View File

@ -28,10 +28,7 @@
}, },
"user": { "user": {
"data": { "data": {
"api_key": "API Key",
"cloud_api": "Geographical Location", "cloud_api": "Geographical Location",
"latitude": "Latitude",
"longitude": "Longitude",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "Integration Type" "type": "Integration Type"
}, },
@ -46,7 +43,6 @@
"data": { "data": {
"show_on_map": "Show monitored geography on the map" "show_on_map": "Show monitored geography on the map"
}, },
"description": "Set various options for the AirVisual integration.",
"title": "Configure AirVisual" "title": "Configure AirVisual"
} }
} }

View File

@ -5,11 +5,13 @@
}, },
"error": { "error": {
"general_error": "Se ha producido un error desconocido.", "general_error": "Se ha producido un error desconocido.",
"invalid_api_key": "Se proporciona una clave de API no v\u00e1lida.",
"unable_to_connect": "No se puede conectar a la unidad Node/Pro." "unable_to_connect": "No se puede conectar a la unidad Node/Pro."
}, },
"step": { "step": {
"geography": { "geography": {
"data": { "data": {
"api_key": "Clave API",
"latitude": "Latitud", "latitude": "Latitud",
"longitude": "Longitud" "longitude": "Longitud"
}, },
@ -26,10 +28,7 @@
}, },
"user": { "user": {
"data": { "data": {
"api_key": "Clave API",
"cloud_api": "Localizaci\u00f3n geogr\u00e1fica", "cloud_api": "Localizaci\u00f3n geogr\u00e1fica",
"latitude": "Latitud",
"longitude": "Longitud",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "Tipo de integraci\u00f3n" "type": "Tipo de integraci\u00f3n"
}, },
@ -44,7 +43,6 @@
"data": { "data": {
"show_on_map": "Mostrar geograf\u00eda monitoreada en el mapa" "show_on_map": "Mostrar geograf\u00eda monitoreada en el mapa"
}, },
"description": "Establezca varias opciones para la integraci\u00f3n de AirVisual.",
"title": "Configurar AirVisual" "title": "Configurar AirVisual"
} }
} }

View File

@ -21,21 +21,18 @@
"node_pro": { "node_pro": {
"data": { "data": {
"ip_address": "Direcci\u00f3n IP/Nombre de host de la Unidad", "ip_address": "Direcci\u00f3n IP/Nombre de host de la Unidad",
"password": "Contrase\u00f1a de la Unidad" "password": "Contrase\u00f1a"
}, },
"description": "Monitorizar una unidad personal AirVisual. La contrase\u00f1a puede ser recuperada desde la interfaz de la unidad.", "description": "Monitorizar una unidad personal AirVisual. La contrase\u00f1a puede ser recuperada desde la interfaz de la unidad.",
"title": "Configurar un AirVisual Node/Pro" "title": "Configurar un AirVisual Node/Pro"
}, },
"user": { "user": {
"data": { "data": {
"api_key": "Clave API",
"cloud_api": "Ubicaci\u00f3n Geogr\u00e1fica", "cloud_api": "Ubicaci\u00f3n Geogr\u00e1fica",
"latitude": "Latitud",
"longitude": "Longitud",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "Tipo de Integraci\u00f3n" "type": "Tipo de Integraci\u00f3n"
}, },
"description": "Elige qu\u00e9 tipo de datos de AirVisual quieres monitorear.", "description": "Elige qu\u00e9 tipo de datos de AirVisual quieres monitorizar.",
"title": "Configurar AirVisual" "title": "Configurar AirVisual"
} }
} }
@ -46,7 +43,6 @@
"data": { "data": {
"show_on_map": "Mostrar geograf\u00eda monitorizada en el mapa" "show_on_map": "Mostrar geograf\u00eda monitorizada en el mapa"
}, },
"description": "Ajustar varias opciones para la integraci\u00f3n de AirVisual.",
"title": "Configurar AirVisual" "title": "Configurar AirVisual"
} }
} }

View File

@ -28,10 +28,7 @@
}, },
"user": { "user": {
"data": { "data": {
"api_key": "Cl\u00e9 API",
"cloud_api": "Localisation g\u00e9ographique", "cloud_api": "Localisation g\u00e9ographique",
"latitude": "Latitude",
"longitude": "Longitude",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "Type d'int\u00e9gration" "type": "Type d'int\u00e9gration"
}, },
@ -46,7 +43,6 @@
"data": { "data": {
"show_on_map": "Afficher la g\u00e9ographie surveill\u00e9e sur la carte" "show_on_map": "Afficher la g\u00e9ographie surveill\u00e9e sur la carte"
}, },
"description": "D\u00e9finissez diverses options pour l'int\u00e9gration d'AirVisual.",
"title": "Configurer AirVisual" "title": "Configurer AirVisual"
} }
} }

View File

@ -6,10 +6,15 @@
"step": { "step": {
"geography": { "geography": {
"data": { "data": {
"api_key": "API Kulcs", "api_key": "API kulcs",
"latitude": "Sz\u00e9less\u00e9g", "latitude": "Sz\u00e9less\u00e9g",
"longitude": "Hossz\u00fas\u00e1g" "longitude": "Hossz\u00fas\u00e1g"
} }
},
"node_pro": {
"data": {
"password": "Jelsz\u00f3"
}
} }
} }
} }

View File

@ -21,17 +21,14 @@
"node_pro": { "node_pro": {
"data": { "data": {
"ip_address": "Indirizzo IP/Nome host dell'unit\u00e0", "ip_address": "Indirizzo IP/Nome host dell'unit\u00e0",
"password": "Password dell'unit\u00e0" "password": "Password"
}, },
"description": "Monitorare un'unit\u00e0 AirVisual personale. La password pu\u00f2 essere recuperata dall'interfaccia utente dell'unit\u00e0.", "description": "Monitorare un'unit\u00e0 AirVisual personale. La password pu\u00f2 essere recuperata dall'interfaccia utente dell'unit\u00e0.",
"title": "Configurare un AirVisual Node/Pro" "title": "Configurare un AirVisual Node/Pro"
}, },
"user": { "user": {
"data": { "data": {
"api_key": "Chiave API",
"cloud_api": "Posizione geografica", "cloud_api": "Posizione geografica",
"latitude": "Latitudine",
"longitude": "Logitudine",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "Tipo di integrazione" "type": "Tipo di integrazione"
}, },
@ -46,7 +43,6 @@
"data": { "data": {
"show_on_map": "Mostra l'area geografica monitorata sulla mappa" "show_on_map": "Mostra l'area geografica monitorata sulla mappa"
}, },
"description": "Impostare varie opzioni per l'integrazione AirVisual.",
"title": "Configurare AirVisual" "title": "Configurare AirVisual"
} }
} }

View File

@ -28,10 +28,7 @@
}, },
"user": { "user": {
"data": { "data": {
"api_key": "API \ud0a4",
"cloud_api": "\uc9c0\ub9ac\uc801 \uc704\uce58", "cloud_api": "\uc9c0\ub9ac\uc801 \uc704\uce58",
"latitude": "\uc704\ub3c4",
"longitude": "\uacbd\ub3c4",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "\uc5f0\ub3d9 \uc720\ud615" "type": "\uc5f0\ub3d9 \uc720\ud615"
}, },
@ -46,7 +43,6 @@
"data": { "data": {
"show_on_map": "\uc9c0\ub3c4\uc5d0 \ubaa8\ub2c8\ud130\ub9c1\ub41c \uc9c0\ub9ac \uc815\ubcf4 \ud45c\uc2dc" "show_on_map": "\uc9c0\ub3c4\uc5d0 \ubaa8\ub2c8\ud130\ub9c1\ub41c \uc9c0\ub9ac \uc815\ubcf4 \ud45c\uc2dc"
}, },
"description": "AirVisual \ud1b5\ud569 \uad6c\uc131\uc694\uc18c\uc5d0 \ub300\ud55c \ub2e4\uc591\ud55c \uc635\uc158\uc744 \uc124\uc815\ud574\uc8fc\uc138\uc694.",
"title": "AirVisual \uad6c\uc131\ud558\uae30" "title": "AirVisual \uad6c\uc131\ud558\uae30"
} }
} }

View File

@ -28,10 +28,7 @@
}, },
"user": { "user": {
"data": { "data": {
"api_key": "API Schl\u00ebssel",
"cloud_api": "Geografesche Standuert", "cloud_api": "Geografesche Standuert",
"latitude": "Breedegrad",
"longitude": "L\u00e4ngegrad",
"node_pro": "Airvisual Node Pro", "node_pro": "Airvisual Node Pro",
"type": "Typ vun der Integratioun" "type": "Typ vun der Integratioun"
}, },
@ -46,7 +43,6 @@
"data": { "data": {
"show_on_map": "Iwwerwaachte Geografie op der Kaart uweisen" "show_on_map": "Iwwerwaachte Geografie op der Kaart uweisen"
}, },
"description": "Verschidden Optioune fir d'AirVisual Integratioun d\u00e9fin\u00e9ieren.",
"title": "Airvisual ariichten" "title": "Airvisual ariichten"
} }
} }

View File

@ -26,10 +26,7 @@
}, },
"user": { "user": {
"data": { "data": {
"api_key": "API-sleutel",
"cloud_api": "Geografische ligging", "cloud_api": "Geografische ligging",
"latitude": "Breedtegraad",
"longitude": "Lengtegraad",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "Integratietype" "type": "Integratietype"
}, },
@ -44,7 +41,6 @@
"data": { "data": {
"show_on_map": "Toon gecontroleerde geografie op de kaart" "show_on_map": "Toon gecontroleerde geografie op de kaart"
}, },
"description": "Stel verschillende opties in voor de AirVisual-integratie.",
"title": "Configureer AirVisual" "title": "Configureer AirVisual"
} }
} }

View File

@ -28,10 +28,7 @@
}, },
"user": { "user": {
"data": { "data": {
"api_key": "API-n\u00f8kkel",
"cloud_api": "Geografisk plassering", "cloud_api": "Geografisk plassering",
"latitude": "Breddegrad",
"longitude": "Lengdegrad",
"node_pro": "", "node_pro": "",
"type": "Integrasjonstype" "type": "Integrasjonstype"
}, },
@ -46,7 +43,6 @@
"data": { "data": {
"show_on_map": "Vis overv\u00e5ket geografi p\u00e5 kartet" "show_on_map": "Vis overv\u00e5ket geografi p\u00e5 kartet"
}, },
"description": "Angi forskjellige alternativer for AirVisual-integrasjonen.",
"title": "Konfigurer AirVisual" "title": "Konfigurer AirVisual"
} }
} }

View File

@ -4,14 +4,14 @@
"already_configured": "Ten klucz API jest ju\u017c w u\u017cyciu." "already_configured": "Ten klucz API jest ju\u017c w u\u017cyciu."
}, },
"error": { "error": {
"general_error": "[%key_id:common::config_flow::error::unknown%]", "general_error": "Nieoczekiwany b\u0142\u0105d.",
"invalid_api_key": "Nieprawid\u0142owy klucz API.", "invalid_api_key": "Nieprawid\u0142owy klucz API.",
"unable_to_connect": "Nie mo\u017cna po\u0142\u0105czy\u0107 si\u0119 z jednostk\u0105 Node/Pro." "unable_to_connect": "Nie mo\u017cna po\u0142\u0105czy\u0107 si\u0119 z jednostk\u0105 Node/Pro."
}, },
"step": { "step": {
"geography": { "geography": {
"data": { "data": {
"api_key": "[%key_id:common::config_flow::data::api_key%]", "api_key": "Klucz API",
"latitude": "Szeroko\u015b\u0107 geograficzna", "latitude": "Szeroko\u015b\u0107 geograficzna",
"longitude": "D\u0142ugo\u015b\u0107 geograficzna" "longitude": "D\u0142ugo\u015b\u0107 geograficzna"
}, },
@ -20,18 +20,15 @@
}, },
"node_pro": { "node_pro": {
"data": { "data": {
"ip_address": "[%key_id:common::config_flow::data::host%]", "ip_address": "Nazwa hosta lub adres IP",
"password": "[%key_id:common::config_flow::data::password%] jednostki" "password": "Has\u0142o"
}, },
"description": "Monitoruj jednostk\u0119 AirVisual. Has\u0142o mo\u017cna odzyska\u0107 z interfejsu u\u017cytkownika urz\u0105dzenia.", "description": "Monitoruj jednostk\u0119 AirVisual. Has\u0142o mo\u017cna odzyska\u0107 z interfejsu u\u017cytkownika urz\u0105dzenia.",
"title": "Konfiguracja AirVisual Node/Pro" "title": "Konfiguracja AirVisual Node/Pro"
}, },
"user": { "user": {
"data": { "data": {
"api_key": "[%key_id:common::config_flow::data::api_key%]",
"cloud_api": "Lokalizacja geograficzna", "cloud_api": "Lokalizacja geograficzna",
"latitude": "Szeroko\u015b\u0107 geograficzna",
"longitude": "D\u0142ugo\u015b\u0107 geograficzna",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "Typ integracji" "type": "Typ integracji"
}, },
@ -46,7 +43,6 @@
"data": { "data": {
"show_on_map": "Wy\u015bwietlaj encje na mapie" "show_on_map": "Wy\u015bwietlaj encje na mapie"
}, },
"description": "Konfiguracja opcji integracji AirVisual.",
"title": "Konfiguracja AirVisual" "title": "Konfiguracja AirVisual"
} }
} }

View File

@ -0,0 +1,21 @@
{
"config": {
"error": {
"general_error": "Ocorreu um erro desconhecido.",
"invalid_api_key": "Chave de API fornecida \u00e9 inv\u00e1lida."
},
"step": {
"geography": {
"data": {
"latitude": "Latitude",
"longitude": "Longitude"
}
},
"user": {
"data": {
"type": "Tipo de Integra\u00e7\u00e3o"
}
}
}
}
}

View File

@ -28,10 +28,7 @@
}, },
"user": { "user": {
"data": { "data": {
"api_key": "\u041a\u043b\u044e\u0447 API",
"cloud_api": "\u041c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435", "cloud_api": "\u041c\u0435\u0441\u0442\u043e\u043f\u043e\u043b\u043e\u0436\u0435\u043d\u0438\u0435",
"latitude": "\u0428\u0438\u0440\u043e\u0442\u0430",
"longitude": "\u0414\u043e\u043b\u0433\u043e\u0442\u0430",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "\u0422\u0438\u043f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438" "type": "\u0422\u0438\u043f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438"
}, },
@ -46,7 +43,6 @@
"data": { "data": {
"show_on_map": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u043c\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043d\u0430 \u043a\u0430\u0440\u0442\u0435" "show_on_map": "\u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0435\u043c\u0443\u044e \u043e\u0431\u043b\u0430\u0441\u0442\u044c \u043d\u0430 \u043a\u0430\u0440\u0442\u0435"
}, },
"description": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438 AirVisual.",
"title": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 AirVisual" "title": "\u041d\u0430\u0441\u0442\u0440\u043e\u0439\u043a\u0438 AirVisual"
} }
} }

View File

@ -28,10 +28,7 @@
}, },
"user": { "user": {
"data": { "data": {
"api_key": "API Klju\u010d",
"cloud_api": "Geografska lokacija", "cloud_api": "Geografska lokacija",
"latitude": "Zemljepisna \u0161irina",
"longitude": "Zemljepisna dol\u017eina",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "Vrsta integracije" "type": "Vrsta integracije"
}, },
@ -46,7 +43,6 @@
"data": { "data": {
"show_on_map": "Prika\u017ei nadzorovano obmo\u010dje na zemljevidu" "show_on_map": "Prika\u017ei nadzorovano obmo\u010dje na zemljevidu"
}, },
"description": "Nastavite razli\u010dne mo\u017enosti za integracijo AirVisual.",
"title": "Nastavite AirVisual" "title": "Nastavite AirVisual"
} }
} }

View File

@ -18,10 +18,7 @@
}, },
"user": { "user": {
"data": { "data": {
"api_key": "API-nyckel",
"cloud_api": "Geografisk Plats", "cloud_api": "Geografisk Plats",
"latitude": "Latitud",
"longitude": "Longitud",
"type": "Integrationstyp" "type": "Integrationstyp"
} }
} }

View File

@ -5,7 +5,7 @@
}, },
"error": { "error": {
"general_error": "\u767c\u751f\u672a\u77e5\u932f\u8aa4\u3002", "general_error": "\u767c\u751f\u672a\u77e5\u932f\u8aa4\u3002",
"invalid_api_key": "API \u5bc6\u78bc\u7121\u6548\u3002", "invalid_api_key": "API \u5bc6\u9470\u7121\u6548\u3002",
"unable_to_connect": "\u7121\u6cd5\u9023\u7dda\u81f3 Node/Pro \u8a2d\u5099\u3002" "unable_to_connect": "\u7121\u6cd5\u9023\u7dda\u81f3 Node/Pro \u8a2d\u5099\u3002"
}, },
"step": { "step": {
@ -28,10 +28,7 @@
}, },
"user": { "user": {
"data": { "data": {
"api_key": "API \u5bc6\u9470",
"cloud_api": "\u5730\u7406\u5ea7\u6a19", "cloud_api": "\u5730\u7406\u5ea7\u6a19",
"latitude": "\u7def\u5ea6",
"longitude": "\u7d93\u5ea6",
"node_pro": "AirVisual Node Pro", "node_pro": "AirVisual Node Pro",
"type": "\u6574\u5408\u985e\u578b" "type": "\u6574\u5408\u985e\u578b"
}, },
@ -46,7 +43,6 @@
"data": { "data": {
"show_on_map": "\u65bc\u5730\u5716\u4e0a\u986f\u793a\u76e3\u63a7\u4f4d\u7f6e\u3002" "show_on_map": "\u65bc\u5730\u5716\u4e0a\u986f\u793a\u76e3\u63a7\u4f4d\u7f6e\u3002"
}, },
"description": "\u8a2d\u5b9a AirVisual \u6574\u5408\u9078\u9805\u3002",
"title": "\u8a2d\u5b9a AirVisual" "title": "\u8a2d\u5b9a AirVisual"
} }
} }

View File

@ -24,13 +24,13 @@
}, },
"state": { "state": {
"_": { "_": {
"armed": "Armado", "armed": "Armada",
"armed_away": "Armada ausente", "armed_away": "Armada ausente",
"armed_custom_bypass": "Armada personalizada", "armed_custom_bypass": "Armada personalizada",
"armed_home": "Armada en casa", "armed_home": "Armada en casa",
"armed_night": "Armada noche", "armed_night": "Armada noche",
"arming": "Armando", "arming": "Armando",
"disarmed": "Desarmado", "disarmed": "Desarmada",
"disarming": "Desarmando", "disarming": "Desarmando",
"pending": "Pendiente", "pending": "Pendiente",
"triggered": "Disparada" "triggered": "Disparada"

View File

@ -7,6 +7,13 @@
"disarm": "Desarmar {entity_name}", "disarm": "Desarmar {entity_name}",
"trigger": "Disparar {entidade_nome}" "trigger": "Disparar {entidade_nome}"
}, },
"condition_type": {
"is_armed_away": "{entity_name} est\u00e1 armado modo longe",
"is_armed_home": "{entity_name} est\u00e1 armadado modo casa",
"is_armed_night": "{entity_name} est\u00e1 armadado modo noite",
"is_disarmed": "{entity_name} est\u00e1 desarmado",
"is_triggered": "{entity_name} est\u00e1 acionado"
},
"trigger_type": { "trigger_type": {
"armed_away": "{entity_name} armado modo longe", "armed_away": "{entity_name} armado modo longe",
"armed_home": "{entity_name} armadado modo casa", "armed_home": "{entity_name} armadado modo casa",

View File

@ -3,15 +3,13 @@ import logging
import voluptuous as vol import voluptuous as vol
from homeassistant.const import CONF_NAME from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, CONF_NAME
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers import config_validation as cv, entityfilter from homeassistant.helpers import config_validation as cv, entityfilter
from . import flash_briefings, intent, smart_home_http from . import flash_briefings, intent, smart_home_http
from .const import ( from .const import (
CONF_AUDIO, CONF_AUDIO,
CONF_CLIENT_ID,
CONF_CLIENT_SECRET,
CONF_DESCRIPTION, CONF_DESCRIPTION,
CONF_DISPLAY_CATEGORIES, CONF_DISPLAY_CATEGORIES,
CONF_DISPLAY_URL, CONF_DISPLAY_URL,

View File

@ -7,7 +7,7 @@ import logging
import aiohttp import aiohttp
import async_timeout import async_timeout
from homeassistant.const import HTTP_OK from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, HTTP_OK
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers import aiohttp_client from homeassistant.helpers import aiohttp_client
from homeassistant.util import dt from homeassistant.util import dt
@ -48,8 +48,8 @@ class Auth:
lwa_params = { lwa_params = {
"grant_type": "authorization_code", "grant_type": "authorization_code",
"code": accept_grant_code, "code": accept_grant_code,
"client_id": self.client_id, CONF_CLIENT_ID: self.client_id,
"client_secret": self.client_secret, CONF_CLIENT_SECRET: self.client_secret,
} }
_LOGGER.debug( _LOGGER.debug(
"Calling LWA to get the access token (first time), with: %s", "Calling LWA to get the access token (first time), with: %s",
@ -80,8 +80,8 @@ class Auth:
lwa_params = { lwa_params = {
"grant_type": "refresh_token", "grant_type": "refresh_token",
"refresh_token": self._prefs[STORAGE_REFRESH_TOKEN], "refresh_token": self._prefs[STORAGE_REFRESH_TOKEN],
"client_id": self.client_id, CONF_CLIENT_ID: self.client_id,
"client_secret": self.client_secret, CONF_CLIENT_SECRET: self.client_secret,
} }
_LOGGER.debug("Calling LWA to refresh the access token.") _LOGGER.debug("Calling LWA to refresh the access token.")

View File

@ -1661,7 +1661,21 @@ class AlexaDoorbellEventSource(AlexaCapability):
https://developer.amazon.com/docs/device-apis/alexa-doorbelleventsource.html https://developer.amazon.com/docs/device-apis/alexa-doorbelleventsource.html
""" """
supported_locales = {"en-US"} supported_locales = {
"en-US",
"de-DE",
"en-AU",
"en-CA",
"en-GB",
"en-IN",
"en-US",
"es-ES",
"es-MX",
"fr-CA",
"fr-FR",
"it-IT",
"ja-JP",
}
def name(self): def name(self):
"""Return the Alexa API name of this interface.""" """Return the Alexa API name of this interface."""
@ -1789,6 +1803,13 @@ class AlexaEqualizerController(AlexaCapability):
""" """
supported_locales = {"en-US"} supported_locales = {"en-US"}
VALID_SOUND_MODES = {
"MOVIE",
"MUSIC",
"NIGHT",
"SPORT",
"TV",
}
def name(self): def name(self):
"""Return the Alexa API name of this interface.""" """Return the Alexa API name of this interface."""
@ -1807,35 +1828,34 @@ class AlexaEqualizerController(AlexaCapability):
raise UnsupportedProperty(name) raise UnsupportedProperty(name)
sound_mode = self.entity.attributes.get(media_player.ATTR_SOUND_MODE) sound_mode = self.entity.attributes.get(media_player.ATTR_SOUND_MODE)
if sound_mode and sound_mode.upper() in ( if sound_mode and sound_mode.upper() in self.VALID_SOUND_MODES:
"MOVIE",
"MUSIC",
"NIGHT",
"SPORT",
"TV",
):
return sound_mode.upper() return sound_mode.upper()
return None return None
def configurations(self): def configurations(self):
"""Return the sound modes supported in the configurations object. """Return the sound modes supported in the configurations object."""
Valid Values for modes are: MOVIE, MUSIC, NIGHT, SPORT, TV.
"""
configurations = None configurations = None
sound_mode_list = self.entity.attributes.get(media_player.ATTR_SOUND_MODE_LIST) supported_sound_modes = self.get_valid_inputs(
if sound_mode_list: self.entity.attributes.get(media_player.ATTR_SOUND_MODE_LIST, [])
supported_sound_modes = [ )
{"name": sound_mode.upper()} if supported_sound_modes:
for sound_mode in sound_mode_list
if sound_mode.upper() in ("MOVIE", "MUSIC", "NIGHT", "SPORT", "TV")
]
configurations = {"modes": {"supported": supported_sound_modes}} configurations = {"modes": {"supported": supported_sound_modes}}
return configurations return configurations
@classmethod
def get_valid_inputs(cls, sound_mode_list):
"""Return list of supported inputs."""
input_list = []
for sound_mode in sound_mode_list:
sound_mode = sound_mode.upper()
if sound_mode in cls.VALID_SOUND_MODES:
input_list.append({"name": sound_mode})
return input_list
class AlexaTimeHoldController(AlexaCapability): class AlexaTimeHoldController(AlexaCapability):
"""Implements Alexa.TimeHoldController. """Implements Alexa.TimeHoldController.

View File

@ -18,8 +18,6 @@ CONF_DISPLAY_URL = "display_url"
CONF_FILTER = "filter" CONF_FILTER = "filter"
CONF_ENTITY_CONFIG = "entity_config" CONF_ENTITY_CONFIG = "entity_config"
CONF_ENDPOINT = "endpoint" CONF_ENDPOINT = "endpoint"
CONF_CLIENT_ID = "client_id"
CONF_CLIENT_SECRET = "client_secret"
CONF_LOCALE = "locale" CONF_LOCALE = "locale"
ATTR_UID = "uid" ATTR_UID = "uid"
@ -126,6 +124,8 @@ class Inputs:
""" """
VALID_SOURCE_NAME_MAP = { VALID_SOURCE_NAME_MAP = {
"antenna": "TUNER",
"antennatv": "TUNER",
"aux": "AUX 1", "aux": "AUX 1",
"aux1": "AUX 1", "aux1": "AUX 1",
"aux2": "AUX 2", "aux2": "AUX 2",
@ -135,6 +135,7 @@ class Inputs:
"aux6": "AUX 6", "aux6": "AUX 6",
"aux7": "AUX 7", "aux7": "AUX 7",
"bluray": "BLURAY", "bluray": "BLURAY",
"blurayplayer": "BLURAY",
"cable": "CABLE", "cable": "CABLE",
"cd": "CD", "cd": "CD",
"coax": "COAX 1", "coax": "COAX 1",
@ -186,6 +187,7 @@ class Inputs:
"playstation": "PLAYSTATION", "playstation": "PLAYSTATION",
"playstation3": "PLAYSTATION 3", "playstation3": "PLAYSTATION 3",
"playstation4": "PLAYSTATION 4", "playstation4": "PLAYSTATION 4",
"rokumediaplayer": "MEDIA PLAYER",
"satellite": "SATELLITE", "satellite": "SATELLITE",
"satellitetv": "SATELLITE", "satellitetv": "SATELLITE",
"smartcast": "SMARTCAST", "smartcast": "SMARTCAST",

View File

@ -547,7 +547,11 @@ class MediaPlayerCapabilities(AlexaEntity):
yield AlexaChannelController(self.entity) yield AlexaChannelController(self.entity)
if supported & media_player.const.SUPPORT_SELECT_SOUND_MODE: if supported & media_player.const.SUPPORT_SELECT_SOUND_MODE:
yield AlexaEqualizerController(self.entity) inputs = AlexaInputController.get_valid_inputs(
self.entity.attributes.get(media_player.const.ATTR_SOUND_MODE_LIST, [])
)
if len(inputs) > 0:
yield AlexaEqualizerController(self.entity)
yield AlexaEndpointHealth(self.hass, self.entity) yield AlexaEndpointHealth(self.hass, self.entity)
yield Alexa(self.hass) yield Alexa(self.hass)

View File

@ -40,6 +40,16 @@ def async_setup(hass):
hass.http.register_view(AlexaIntentsView) hass.http.register_view(AlexaIntentsView)
async def async_setup_intents(hass):
"""
Do intents setup.
Right now this module does not expose any, but the intent component breaks
without it.
"""
pass # pylint: disable=unnecessary-pass
class UnknownRequest(HomeAssistantError): class UnknownRequest(HomeAssistantError):
"""When an unknown Alexa request is passed in.""" """When an unknown Alexa request is passed in."""

View File

@ -3,17 +3,11 @@ import logging
from homeassistant import core from homeassistant import core
from homeassistant.components.http.view import HomeAssistantView from homeassistant.components.http.view import HomeAssistantView
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
from .auth import Auth from .auth import Auth
from .config import AbstractConfig from .config import AbstractConfig
from .const import ( from .const import CONF_ENDPOINT, CONF_ENTITY_CONFIG, CONF_FILTER, CONF_LOCALE
CONF_CLIENT_ID,
CONF_CLIENT_SECRET,
CONF_ENDPOINT,
CONF_ENTITY_CONFIG,
CONF_FILTER,
CONF_LOCALE,
)
from .smart_home import async_handle_message from .smart_home import async_handle_message
from .state_report import async_enable_proactive_mode from .state_report import async_enable_proactive_mode

View File

@ -13,7 +13,13 @@ import voluptuous as vol
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.auth.const import GROUP_ID_ADMIN from homeassistant.auth.const import GROUP_ID_ADMIN
from homeassistant.components import conversation from homeassistant.components import conversation
from homeassistant.const import CONF_HOST, CONF_TYPE, EVENT_HOMEASSISTANT_START from homeassistant.const import (
CONF_CLIENT_ID,
CONF_CLIENT_SECRET,
CONF_HOST,
CONF_TYPE,
EVENT_HOMEASSISTANT_START,
)
from homeassistant.core import Context, CoreState, HomeAssistant from homeassistant.core import Context, CoreState, HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import ( from homeassistant.helpers import (
@ -29,9 +35,6 @@ from homeassistant.helpers import (
from . import config_flow from . import config_flow
from .const import DOMAIN, TYPE_LOCAL, TYPE_OAUTH2 from .const import DOMAIN, TYPE_LOCAL, TYPE_OAUTH2
CONF_CLIENT_ID = "client_id"
CONF_CLIENT_SECRET = "client_secret"
STORAGE_VERSION = 1 STORAGE_VERSION = 1
STORAGE_KEY = DOMAIN STORAGE_KEY = DOMAIN

View File

@ -7,11 +7,11 @@
}, },
"step": { "step": {
"hassio_confirm": { "hassio_confirm": {
"description": "Czy chcesz skonfigurowa\u0107 Home Assistant'a, aby \u0142\u0105czy\u0142 si\u0119 z Almond dostarczonym przez dodatek Hass.io: {addon}?", "description": "Czy chcesz skonfigurowa\u0107 Home Assistanta, aby \u0142\u0105czy\u0142 si\u0119 z Almond dostarczonym przez dodatek Hass.io: {addon}?",
"title": "Almond poprzez dodatek Hass.io" "title": "Almond poprzez dodatek Hass.io"
}, },
"pick_implementation": { "pick_implementation": {
"title": "[%key_id:common::config_flow::title::oauth2_pick_implementation%]" "title": "Wybierz metod\u0119 uwierzytelniania"
} }
} }
} }

View File

@ -3,10 +3,11 @@ import logging
import voluptuous as vol import voluptuous as vol
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from . import config_flow from . import config_flow
from .const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, DOMAIN from .const import DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)

View File

@ -11,14 +11,18 @@ from homeassistant.components.climate.const import (
HVAC_MODE_OFF, HVAC_MODE_OFF,
SUPPORT_TARGET_TEMPERATURE, SUPPORT_TARGET_TEMPERATURE,
) )
from homeassistant.const import ATTR_NAME, ATTR_TEMPERATURE, TEMP_CELSIUS from homeassistant.const import (
ATTR_NAME,
ATTR_TEMPERATURE,
CONF_CLIENT_ID,
CONF_CLIENT_SECRET,
TEMP_CELSIUS,
)
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 .const import ( from .const import (
ATTR_VALUE, ATTR_VALUE,
CONF_CLIENT_ID,
CONF_CLIENT_SECRET,
DOMAIN, DOMAIN,
SERVICE_COMFORT_FEEDBACK, SERVICE_COMFORT_FEEDBACK,
SERVICE_COMFORT_MODE, SERVICE_COMFORT_MODE,

View File

@ -5,6 +5,7 @@ import ambiclimate
from homeassistant import config_entries from homeassistant import config_entries
from homeassistant.components.http import HomeAssistantView from homeassistant.components.http import HomeAssistantView
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.network import get_url from homeassistant.helpers.network import get_url
@ -12,8 +13,6 @@ from homeassistant.helpers.network import get_url
from .const import ( from .const import (
AUTH_CALLBACK_NAME, AUTH_CALLBACK_NAME,
AUTH_CALLBACK_PATH, AUTH_CALLBACK_PATH,
CONF_CLIENT_ID,
CONF_CLIENT_SECRET,
DOMAIN, DOMAIN,
STORAGE_KEY, STORAGE_KEY,
STORAGE_VERSION, STORAGE_VERSION,

View File

@ -1,12 +1,13 @@
"""Constants used by the Ambiclimate component.""" """Constants used by the Ambiclimate component."""
ATTR_VALUE = "value"
CONF_CLIENT_ID = "client_id"
CONF_CLIENT_SECRET = "client_secret"
DOMAIN = "ambiclimate" DOMAIN = "ambiclimate"
ATTR_VALUE = "value"
SERVICE_COMFORT_FEEDBACK = "send_comfort_feedback" SERVICE_COMFORT_FEEDBACK = "send_comfort_feedback"
SERVICE_COMFORT_MODE = "set_comfort_mode" SERVICE_COMFORT_MODE = "set_comfort_mode"
SERVICE_TEMPERATURE_MODE = "set_temperature_mode" SERVICE_TEMPERATURE_MODE = "set_temperature_mode"
STORAGE_KEY = "ambiclimate_auth" STORAGE_KEY = "ambiclimate_auth"
STORAGE_VERSION = 1 STORAGE_VERSION = 1

View File

@ -14,7 +14,7 @@
}, },
"step": { "step": {
"auth": { "auth": {
"description": "\u041c\u043e\u043b\u044f, \u043f\u043e\u0441\u043b\u0435\u0434\u0432\u0430\u0439\u0442\u0435 \u0442\u043e\u0437\u0438 [link]({authorization_url}) \u0438 <b>\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u0442\u0435</b> \u0434\u043e\u0441\u0442\u044a\u043f\u0430 \u0434\u043e \u043f\u0440\u043e\u0444\u0438\u043b\u0430 \u0441\u0438 \u0432 Ambiclimate, \u0441\u043b\u0435\u0434 \u0442\u043e\u0432\u0430 \u0441\u0435 \u0432\u044a\u0440\u043d\u0435\u0442\u0435 \u0438 \u043d\u0430\u0442\u0438\u0441\u043d\u0435\u0442\u0435 <b>\u0418\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435</b> \u043f\u043e-\u0434\u043e\u043b\u0443. \n (\u0423\u0432\u0435\u0440\u0435\u0442\u0435 \u0441\u0435, \u0447\u0435 \u043f\u043e\u0441\u043e\u0447\u0435\u043d\u0438\u044f\u0442 url \u0437\u0430 \u043e\u0431\u0440\u0430\u0442\u043d\u0430 \u043f\u043e\u0432\u0438\u043a\u0432\u0430\u043d\u0435 \u0435 {cb_url})", "description": "\u041c\u043e\u043b\u044f, \u043f\u043e\u0441\u043b\u0435\u0434\u0432\u0430\u0439\u0442\u0435 \u0442\u043e\u0437\u0438 [link]({authorization_url}) \u0438 **\u0420\u0430\u0437\u0440\u0435\u0448\u0435\u0442\u0435** \u0434\u043e\u0441\u0442\u044a\u043f\u0430 \u0434\u043e \u043f\u0440\u043e\u0444\u0438\u043b\u0430 \u0441\u0438 \u0432 Ambiclimate, \u0441\u043b\u0435\u0434 \u0442\u043e\u0432\u0430 \u0441\u0435 \u0432\u044a\u0440\u043d\u0435\u0442\u0435 \u0438 \u043d\u0430\u0442\u0438\u0441\u043d\u0435\u0442\u0435 **\u0418\u0437\u043f\u0440\u0430\u0449\u0430\u043d\u0435** \u043f\u043e-\u0434\u043e\u043b\u0443. \n (\u0423\u0432\u0435\u0440\u0435\u0442\u0435 \u0441\u0435, \u0447\u0435 \u043f\u043e\u0441\u043e\u0447\u0435\u043d\u0438\u044f\u0442 url \u0437\u0430 \u043e\u0431\u0440\u0430\u0442\u043d\u0430 \u043f\u043e\u0432\u0438\u043a\u0432\u0430\u043d\u0435 \u0435 {cb_url})",
"title": "\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u043a\u0438\u0440\u0430\u043d\u0435 \u0441 Ambiclimate" "title": "\u0410\u0443\u0442\u0435\u043d\u0442\u0438\u043a\u0438\u0440\u0430\u043d\u0435 \u0441 Ambiclimate"
} }
} }

View File

@ -14,7 +14,7 @@
}, },
"step": { "step": {
"auth": { "auth": {
"description": "V\u00e9s a l'[enlla\u00e7]({authorization_url}) i <b>Permet</b> l'acc\u00e9s al teu compte de Ambiclimate, despr\u00e9s torna i prem <b>Envia</b> (a sota).\n(Assegura't que l'enlla\u00e7 de retorn \u00e9s el seg\u00fcent {cb_url})", "description": "V\u00e9s a l'[enlla\u00e7]({authorization_url}) i **Permet** l'acc\u00e9s al teu compte de Ambiclimate, despr\u00e9s torna i prem **Envia** (a sota).\n(Assegura't que l'enlla\u00e7 de retorn \u00e9s el seg\u00fcent {cb_url})",
"title": "Autenticaci\u00f3 amb Ambi Climate" "title": "Autenticaci\u00f3 amb Ambi Climate"
} }
} }

View File

@ -6,7 +6,7 @@
}, },
"step": { "step": {
"auth": { "auth": {
"description": "N\u00e1sledujte tento [odkaz]({authorization_url}) a <b> Povolit </b> p\u0159\u00edstup k va\u0161emu \u00fa\u010dtu Ambiclimate, pot\u00e9 se vra\u0165te a stiskn\u011bte <b> Odeslat </b> n\u00ed\u017ee. \n (Ujist\u011bte se, \u017ee zadan\u00e1 adresa URL zp\u011btn\u00e9ho vol\u00e1n\u00ed je {cb_url} )", "description": "N\u00e1sledujte tento [odkaz]({authorization_url}) a **Povolit** p\u0159\u00edstup k va\u0161emu \u00fa\u010dtu Ambiclimate, pot\u00e9 se vra\u0165te a stiskn\u011bte **Odeslat** n\u00ed\u017ee. \n (Ujist\u011bte se, \u017ee zadan\u00e1 adresa URL zp\u011btn\u00e9ho vol\u00e1n\u00ed je {cb_url} )",
"title": "Ov\u011b\u0159it Ambiclimate" "title": "Ov\u011b\u0159it Ambiclimate"
} }
} }

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