commit
818b45384d
37
.coveragerc
37
.coveragerc
|
@ -10,6 +10,14 @@ omit =
|
|||
# omit pieces of code that rely on external devices being present
|
||||
homeassistant/components/acer_projector/switch.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/const.py
|
||||
homeassistant/components/adguard/sensor.py
|
||||
|
@ -55,14 +63,9 @@ omit =
|
|||
homeassistant/components/arwn/sensor.py
|
||||
homeassistant/components/asterisk_cdr/mailbox.py
|
||||
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/atome/*
|
||||
homeassistant/components/aurora_abb_powerone/sensor.py
|
||||
homeassistant/components/automatic/*
|
||||
homeassistant/components/avea/light.py
|
||||
homeassistant/components/avion/light.py
|
||||
homeassistant/components/avri/sensor.py
|
||||
|
@ -115,6 +118,7 @@ omit =
|
|||
homeassistant/components/cast/*
|
||||
homeassistant/components/cert_expiry/helper.py
|
||||
homeassistant/components/channels/*
|
||||
homeassistant/components/circuit/*
|
||||
homeassistant/components/cisco_ios/device_tracker.py
|
||||
homeassistant/components/cisco_mobility_express/device_tracker.py
|
||||
homeassistant/components/cisco_webex_teams/notify.py
|
||||
|
@ -172,6 +176,8 @@ omit =
|
|||
homeassistant/components/dsmr_reader/*
|
||||
homeassistant/components/dte_energy_bridge/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/dwd_weather_warnings/sensor.py
|
||||
homeassistant/components/dweet/*
|
||||
|
@ -271,7 +277,6 @@ omit =
|
|||
homeassistant/components/garmin_connect/sensor.py
|
||||
homeassistant/components/gc100/*
|
||||
homeassistant/components/geniushub/*
|
||||
homeassistant/components/gearbest/sensor.py
|
||||
homeassistant/components/geizhals/sensor.py
|
||||
homeassistant/components/gios/__init__.py
|
||||
homeassistant/components/gios/air_quality.py
|
||||
|
@ -282,7 +287,6 @@ omit =
|
|||
homeassistant/components/glances/sensor.py
|
||||
homeassistant/components/gntp/notify.py
|
||||
homeassistant/components/goalfeed/*
|
||||
homeassistant/components/gogogate2/cover.py
|
||||
homeassistant/components/google/*
|
||||
homeassistant/components/google_cloud/tts.py
|
||||
homeassistant/components/google_maps/device_tracker.py
|
||||
|
@ -296,6 +300,10 @@ omit =
|
|||
homeassistant/components/growatt_server/sensor.py
|
||||
homeassistant/components/gstreamer/media_player.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/hangouts/*
|
||||
homeassistant/components/hangouts/__init__.py
|
||||
|
@ -557,7 +565,9 @@ omit =
|
|||
homeassistant/components/openevse/sensor.py
|
||||
homeassistant/components/openexchangerates/sensor.py
|
||||
homeassistant/components/opengarage/cover.py
|
||||
homeassistant/components/openhome/__init__.py
|
||||
homeassistant/components/openhome/media_player.py
|
||||
homeassistant/components/openhome/const.py
|
||||
homeassistant/components/opensensemap/air_quality.py
|
||||
homeassistant/components/opensky/sensor.py
|
||||
homeassistant/components/opentherm_gw/__init__.py
|
||||
|
@ -595,7 +605,11 @@ omit =
|
|||
homeassistant/components/plaato/*
|
||||
homeassistant/components/plex/media_player.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/pocketcasts/sensor.py
|
||||
homeassistant/components/point/*
|
||||
|
@ -718,7 +732,6 @@ omit =
|
|||
homeassistant/components/soma/__init__.py
|
||||
homeassistant/components/somfy/*
|
||||
homeassistant/components/somfy_mylink/*
|
||||
homeassistant/components/sonarr/sensor.py
|
||||
homeassistant/components/sonos/*
|
||||
homeassistant/components/sony_projector/switch.py
|
||||
homeassistant/components/spc/*
|
||||
|
@ -748,6 +761,7 @@ omit =
|
|||
homeassistant/components/synology/camera.py
|
||||
homeassistant/components/synology_chat/notify.py
|
||||
homeassistant/components/synology_dsm/__init__.py
|
||||
homeassistant/components/synology_dsm/binary_sensor.py
|
||||
homeassistant/components/synology_dsm/sensor.py
|
||||
homeassistant/components/synology_srm/device_tracker.py
|
||||
homeassistant/components/syslog/notify.py
|
||||
|
@ -872,9 +886,6 @@ omit =
|
|||
homeassistant/components/wirelesstag/*
|
||||
homeassistant/components/worldtidesinfo/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/xbox_live/sensor.py
|
||||
homeassistant/components/xeoma/camera.py
|
||||
|
@ -922,7 +933,7 @@ omit =
|
|||
homeassistant/components/zha/light.py
|
||||
homeassistant/components/zha/sensor.py
|
||||
homeassistant/components/zhong_hong/climate.py
|
||||
homeassistant/components/zigbee/*
|
||||
homeassistant/components/xbee/*
|
||||
homeassistant/components/ziggo_mediabox_xl/media_player.py
|
||||
homeassistant/components/zoneminder/*
|
||||
homeassistant/components/supla/*
|
||||
|
|
|
@ -106,6 +106,7 @@ virtualization/vagrant/config
|
|||
!.vscode/cSpell.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/tasks.json
|
||||
.env
|
||||
|
||||
# Built docs
|
||||
docs/build
|
||||
|
|
|
@ -22,7 +22,7 @@ repos:
|
|||
- --quiet-level=2
|
||||
exclude_types: [csv, json]
|
||||
- repo: https://gitlab.com/pycqa/flake8
|
||||
rev: 3.7.9
|
||||
rev: 3.8.1
|
||||
hooks:
|
||||
- id: flake8
|
||||
additional_dependencies:
|
||||
|
@ -80,8 +80,8 @@ repos:
|
|||
entry: script/run-in-env.sh python3 -m script.gen_requirements_all
|
||||
pass_filenames: false
|
||||
language: script
|
||||
types: [json]
|
||||
files: ^homeassistant/.+/manifest\.json$
|
||||
types: [text]
|
||||
files: ^(homeassistant/.+/manifest\.json|\.pre-commit-config\.yaml)$
|
||||
- id: hassfest
|
||||
name: hassfest
|
||||
entry: script/run-in-env.sh python3 -m script.hassfest
|
||||
|
|
18
CODEOWNERS
18
CODEOWNERS
|
@ -14,6 +14,7 @@ homeassistant/scripts/check_config.py @kellerza
|
|||
|
||||
# Integrations
|
||||
homeassistant/components/abode/* @shred86
|
||||
homeassistant/components/acmeda/* @atmurray
|
||||
homeassistant/components/adguard/* @frenck
|
||||
homeassistant/components/agent_dvr/* @ispysoftware
|
||||
homeassistant/components/airly/* @bieniu
|
||||
|
@ -42,7 +43,6 @@ homeassistant/components/atome/* @baqs
|
|||
homeassistant/components/august/* @bdraco
|
||||
homeassistant/components/aurora_abb_powerone/* @davet2001
|
||||
homeassistant/components/auth/* @home-assistant/core
|
||||
homeassistant/components/automatic/* @armills
|
||||
homeassistant/components/automation/* @home-assistant/core
|
||||
homeassistant/components/avea/* @pattyland
|
||||
homeassistant/components/avri/* @timvancann
|
||||
|
@ -68,6 +68,7 @@ homeassistant/components/bt_smarthub/* @jxwolstenholme
|
|||
homeassistant/components/buienradar/* @mjj4791 @ties
|
||||
homeassistant/components/cast/* @emontnemery
|
||||
homeassistant/components/cert_expiry/* @Cereal2nd @jjlawren
|
||||
homeassistant/components/circuit/* @braam
|
||||
homeassistant/components/cisco_ios/* @fbradyirl
|
||||
homeassistant/components/cisco_mobility_express/* @fbradyirl
|
||||
homeassistant/components/cisco_webex_teams/* @fbradyirl
|
||||
|
@ -86,7 +87,7 @@ homeassistant/components/cups/* @fabaff
|
|||
homeassistant/components/daikin/* @fredrike
|
||||
homeassistant/components/darksky/* @fabaff
|
||||
homeassistant/components/deconz/* @Kane610
|
||||
homeassistant/components/delijn/* @bollewolle
|
||||
homeassistant/components/delijn/* @bollewolle @Emilv2
|
||||
homeassistant/components/demo/* @home-assistant/core
|
||||
homeassistant/components/denonavr/* @scarface-4711 @starkillerOG
|
||||
homeassistant/components/derivative/* @afaucogney
|
||||
|
@ -97,6 +98,7 @@ homeassistant/components/directv/* @ctalkington
|
|||
homeassistant/components/discogs/* @thibmaek
|
||||
homeassistant/components/doorbird/* @oblogic7 @bdraco
|
||||
homeassistant/components/dsmr_reader/* @depl0y
|
||||
homeassistant/components/dunehd/* @bieniu
|
||||
homeassistant/components/dweet/* @fabaff
|
||||
homeassistant/components/dynalite/* @ziv1234
|
||||
homeassistant/components/dyson/* @etheralm
|
||||
|
@ -140,7 +142,6 @@ homeassistant/components/fronius/* @nielstron
|
|||
homeassistant/components/frontend/* @home-assistant/frontend
|
||||
homeassistant/components/garmin_connect/* @cyberjunky
|
||||
homeassistant/components/gdacs/* @exxamalte
|
||||
homeassistant/components/gearbest/* @HerrHofrat
|
||||
homeassistant/components/geniushub/* @zxdavb
|
||||
homeassistant/components/geo_rss_events/* @exxamalte
|
||||
homeassistant/components/geonetnz_quakes/* @exxamalte
|
||||
|
@ -149,6 +150,7 @@ homeassistant/components/gios/* @bieniu
|
|||
homeassistant/components/gitter/* @fabaff
|
||||
homeassistant/components/glances/* @fabaff @engrbm87
|
||||
homeassistant/components/gntp/* @robbiet480
|
||||
homeassistant/components/gogogate2/* @vangorra
|
||||
homeassistant/components/google_assistant/* @home-assistant/cloud
|
||||
homeassistant/components/google_cloud/* @lufton
|
||||
homeassistant/components/google_translate/* @awarecan
|
||||
|
@ -159,6 +161,7 @@ homeassistant/components/griddy/* @bdraco
|
|||
homeassistant/components/group/* @home-assistant/core
|
||||
homeassistant/components/growatt_server/* @indykoning
|
||||
homeassistant/components/gtfs/* @robbiet480
|
||||
homeassistant/components/guardian/* @bachya
|
||||
homeassistant/components/harmony/* @ehendrix23 @bramkragten @bdraco
|
||||
homeassistant/components/hassio/* @home-assistant/hass-io
|
||||
homeassistant/components/heatmiser/* @andylockran
|
||||
|
@ -178,7 +181,7 @@ homeassistant/components/homematicip_cloud/* @SukramJ
|
|||
homeassistant/components/honeywell/* @zxdavb
|
||||
homeassistant/components/html5/* @robbiet480
|
||||
homeassistant/components/http/* @home-assistant/core
|
||||
homeassistant/components/huawei_lte/* @scop
|
||||
homeassistant/components/huawei_lte/* @scop @fphammerle
|
||||
homeassistant/components/huawei_router/* @abmantis
|
||||
homeassistant/components/hue/* @balloob
|
||||
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_select/* @home-assistant/core
|
||||
homeassistant/components/input_text/* @home-assistant/core
|
||||
homeassistant/components/insteon/* @teharris1
|
||||
homeassistant/components/integration/* @dgomes
|
||||
homeassistant/components/intent/* @home-assistant/core
|
||||
homeassistant/components/intesishome/* @jnimmo
|
||||
|
@ -306,11 +310,11 @@ homeassistant/components/pilight/* @trekky12
|
|||
homeassistant/components/plaato/* @JohNan
|
||||
homeassistant/components/plant/* @ChristianKuehnel
|
||||
homeassistant/components/plex/* @jjlawren
|
||||
homeassistant/components/plugwise/* @laetificat @CoMPaTech @bouwew
|
||||
homeassistant/components/plugwise/* @CoMPaTech @bouwew
|
||||
homeassistant/components/plum_lightpad/* @ColinHarrington
|
||||
homeassistant/components/point/* @fredrike
|
||||
homeassistant/components/powerwall/* @bdraco @jrester
|
||||
homeassistant/components/proxmoxve/* @k4ds3
|
||||
homeassistant/components/proxmoxve/* @k4ds3 @jhollowe
|
||||
homeassistant/components/ps4/* @ktnrg45
|
||||
homeassistant/components/ptvsd/* @swamp-ig
|
||||
homeassistant/components/push/* @dgomes
|
||||
|
@ -370,7 +374,6 @@ homeassistant/components/soma/* @ratsept
|
|||
homeassistant/components/somfy/* @tetienne
|
||||
homeassistant/components/sonarr/* @ctalkington
|
||||
homeassistant/components/songpal/* @rytilahti @shenxn
|
||||
homeassistant/components/sonos/* @amelchio
|
||||
homeassistant/components/spaceapi/* @fabaff
|
||||
homeassistant/components/speedtestdotnet/* @rohankapoorcom
|
||||
homeassistant/components/spider/* @peternijssen
|
||||
|
@ -456,7 +459,6 @@ homeassistant/components/withings/* @vangorra
|
|||
homeassistant/components/wled/* @frenck
|
||||
homeassistant/components/workday/* @fabaff
|
||||
homeassistant/components/worldclock/* @fabaff
|
||||
homeassistant/components/wwlln/* @bachya
|
||||
homeassistant/components/xbox_live/* @MartinHjelmare
|
||||
homeassistant/components/xfinity/* @cisasteelersfan
|
||||
homeassistant/components/xiaomi_aqara/* @danielhiversen @syssi
|
||||
|
|
|
@ -2,79 +2,139 @@
|
|||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
We as members, contributors, and leaders pledge to make participation in our
|
||||
community a harassment-free experience for everyone, regardless of age, body
|
||||
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||
identity and expression, level of experience, education, socio-economic status,
|
||||
nationality, personal appearance, race, religion, or sexual identity
|
||||
and orientation.
|
||||
|
||||
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||
diverse, inclusive, and healthy community.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
Examples of behavior that contributes to a positive environment for our
|
||||
community include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
* Demonstrating empathy and kindness toward other people
|
||||
* Being respectful of differing opinions, viewpoints, and experiences
|
||||
* Giving and gracefully accepting constructive feedback
|
||||
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||
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
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* The use of sexualized language or imagery, and sexual attention or
|
||||
advances of any kind
|
||||
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Publishing others' private information, such as a physical or email
|
||||
address, without their explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
## Enforcement Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
Community leaders are responsible for clarifying and enforcing our standards of
|
||||
acceptable behavior and will take appropriate and fair corrective action in
|
||||
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||
or harmful.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
Community leaders have the right and responsibility to remove, edit, or reject
|
||||
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||
decisions when appropriate.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, 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
|
||||
further defined and clarified by project maintainers.
|
||||
This Code of Conduct applies within all community spaces, and also applies when
|
||||
an individual is officially representing the community in public spaces.
|
||||
Examples of representing our community include using an official e-mail address,
|
||||
posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at [safety@home-assistant.io][email]. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
reported to the community leaders responsible for enforcement at
|
||||
[safety@home-assistant.io][email] or by using the report/flag feature of
|
||||
the medium used. All complaints will be reviewed and investigated promptly and
|
||||
fairly.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
All community leaders are obligated to respect the privacy and security of the
|
||||
reporter of any incident.
|
||||
|
||||
## 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
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available [here][version].
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||
version 2.0, available [here][version].
|
||||
|
||||
Community Impact Guidelines were inspired by [Mozilla's code of conduct
|
||||
enforcement ladder][mozilla].
|
||||
|
||||
## 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
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
For answers to common questions about this code of conduct, see the FAQ at
|
||||
<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
|
||||
[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
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM python:3.8
|
||||
FROM mcr.microsoft.com/vscode/devcontainers/python:0-3.8
|
||||
|
||||
RUN \
|
||||
apt-get update && apt-get install -y --no-install-recommends \
|
||||
|
|
|
@ -158,7 +158,7 @@ stages:
|
|||
steps:
|
||||
- template: templates/azp-step-cache.yaml@azure
|
||||
parameters:
|
||||
keyfile: "requirements_test_all.txt | homeassistant/package_constraints.txt"
|
||||
keyfile: "requirements_test_all.txt | requirements_test.txt | homeassistant/package_constraints.txt"
|
||||
build: |
|
||||
set -e
|
||||
python -m venv venv
|
||||
|
|
|
@ -14,15 +14,14 @@ import voluptuous as vol
|
|||
from homeassistant import config as conf_util, config_entries, core, loader
|
||||
from homeassistant.components import http
|
||||
from homeassistant.const import (
|
||||
EVENT_HOMEASSISTANT_CLOSE,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
REQUIRED_NEXT_PYTHON_DATE,
|
||||
REQUIRED_NEXT_PYTHON_VER,
|
||||
)
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
from homeassistant.helpers.typing import ConfigType
|
||||
from homeassistant.setup import DATA_SETUP, async_setup_component
|
||||
from homeassistant.util.logging import AsyncHandler
|
||||
from homeassistant.setup import DATA_SETUP, DATA_SETUP_STARTED, async_setup_component
|
||||
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.yaml import clear_secret_cache
|
||||
|
||||
|
@ -33,6 +32,8 @@ ERROR_LOG_FILENAME = "home-assistant.log"
|
|||
# hass.data key for logging information.
|
||||
DATA_LOGGING = "logging"
|
||||
|
||||
LOG_SLOW_STARTUP_INTERVAL = 60
|
||||
|
||||
DEBUGGER_INTEGRATIONS = {"ptvsd"}
|
||||
CORE_INTEGRATIONS = ("homeassistant", "persistent_notification")
|
||||
LOGGING_INTEGRATIONS = {"logger", "system_log", "sentry"}
|
||||
|
@ -43,6 +44,13 @@ STAGE_1_INTEGRATIONS = {
|
|||
"mqtt_eventstream",
|
||||
# To provide account link implementations
|
||||
"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.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.addHandler(async_handler) # type: ignore
|
||||
logger.setLevel(logging.INFO)
|
||||
logger.addHandler(err_handler)
|
||||
logger.setLevel(logging.INFO if verbose else logging.WARNING)
|
||||
|
||||
# Save the log file location for access by other components.
|
||||
hass.data[DATA_LOGGING] = err_log_path
|
||||
else:
|
||||
_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:
|
||||
"""Add local library to Python Path.
|
||||
|
@ -331,13 +332,30 @@ async def _async_set_up_integrations(
|
|||
) -> None:
|
||||
"""Set up all the integrations."""
|
||||
|
||||
setup_started = hass.data[DATA_SETUP_STARTED] = {}
|
||||
|
||||
async def async_setup_multi_components(domains: Set[str]) -> None:
|
||||
"""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 = {
|
||||
domain: hass.async_create_task(async_setup_component(hass, domain, config))
|
||||
for domain in domains
|
||||
}
|
||||
log_task = asyncio.create_task(_async_log_pending_setups())
|
||||
await asyncio.wait(futures.values())
|
||||
log_task.cancel()
|
||||
errors = [domain for domain in domains if futures[domain].exception()]
|
||||
for domain in errors:
|
||||
exception = futures[domain].exception()
|
||||
|
@ -388,6 +406,8 @@ async def _async_set_up_integrations(
|
|||
)
|
||||
|
||||
if stage_1_domains:
|
||||
_LOGGER.info("Setting up %s", stage_1_domains)
|
||||
|
||||
await async_setup_multi_components(stage_1_domains)
|
||||
|
||||
# Load all integrations
|
||||
|
@ -430,4 +450,5 @@ async def _async_set_up_integrations(
|
|||
await async_setup_multi_components(stage_2_domains)
|
||||
|
||||
# Wrap up startup
|
||||
_LOGGER.debug("Waiting for startup to wrap up")
|
||||
await hass.async_block_till_done()
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"user": {
|
||||
"data": {
|
||||
"password": "Jelsz\u00f3",
|
||||
"username": "Email c\u00edm"
|
||||
"username": "E-mail"
|
||||
},
|
||||
"title": "T\u00f6ltse ki az Abode bejelentkez\u00e9si adatait"
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
"user": {
|
||||
"data": {
|
||||
"password": "Password",
|
||||
"username": "Indirizzo email"
|
||||
"username": "E-mail"
|
||||
},
|
||||
"title": "Inserisci le tue informazioni di accesso Abode"
|
||||
}
|
||||
|
|
|
@ -11,8 +11,8 @@
|
|||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"password": "[%key_id:common::config_flow::data::password%]",
|
||||
"username": "[%key_id:common::config_flow::data::email%]"
|
||||
"password": "Has\u0142o",
|
||||
"username": "Adres e-mail"
|
||||
},
|
||||
"title": "Wprowad\u017a informacje logowania Abode"
|
||||
}
|
||||
|
|
|
@ -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
|
|
@ -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),
|
||||
}
|
|
@ -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})
|
|
@ -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_{}"
|
|
@ -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])
|
|
@ -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."""
|
|
@ -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,
|
||||
)
|
|
@ -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)
|
||||
)
|
|
@ -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"
|
||||
]
|
||||
}
|
|
@ -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
|
|
@ -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."
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -3,8 +3,7 @@
|
|||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"latitude": "Latitude",
|
||||
"longitude": "Longitude"
|
||||
"id": "Host-ID"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"config": {
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"id": "ID de l'h\u00f4te"
|
||||
},
|
||||
"title": "Choisissez un hub \u00e0 ajouter"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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": ""
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -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"
|
||||
}
|
|
@ -21,8 +21,7 @@
|
|||
"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"
|
||||
},
|
||||
"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."
|
||||
"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."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
"username": "[%key::common::config_flow::data::username%]",
|
||||
"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.",
|
||||
"title": "Enlla\u00e7ar AdGuard Home."
|
||||
"description": "Configuraci\u00f3 de la inst\u00e0ncia d'AdGuard Home, permet el control i la monitoritzaci\u00f3."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,7 @@
|
|||
"username": "Brugernavn",
|
||||
"verify_ssl": "AdGuard Home bruger et korrekt certifikat"
|
||||
},
|
||||
"description": "Konfigurer din AdGuard Home-instans for at tillade overv\u00e5gning og kontrol.",
|
||||
"title": "Forbind din AdGuard Home."
|
||||
"description": "Konfigurer din AdGuard Home-instans for at tillade overv\u00e5gning og kontrol."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
"username": "Benutzername",
|
||||
"verify_ssl": "AdGuard Home verwendet ein richtiges Zertifikat"
|
||||
},
|
||||
"description": "Richte deine AdGuard Home-Instanz ein um sie zu \u00dcberwachen und zu Steuern.",
|
||||
"title": "Verkn\u00fcpfe AdGuard Home."
|
||||
"description": "Richte deine AdGuard Home-Instanz ein um sie zu \u00dcberwachen und zu Steuern."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
"username": "Username",
|
||||
"verify_ssl": "AdGuard Home uses a proper certificate"
|
||||
},
|
||||
"description": "Set up your AdGuard Home instance to allow monitoring and control.",
|
||||
"title": "Link your AdGuard Home."
|
||||
"description": "Set up your AdGuard Home instance to allow monitoring and control."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,13 +16,14 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "Host",
|
||||
"password": "Contrase\u00f1a",
|
||||
"port": "Puerto",
|
||||
"ssl": "AdGuard Home utiliza un certificado SSL",
|
||||
"username": "Nombre de usuario",
|
||||
"verify_ssl": "AdGuard Home utiliza un certificado adecuado"
|
||||
},
|
||||
"description": "Configure su instancia de AdGuard Home para permitir la supervisi\u00f3n y el control.",
|
||||
"title": "Enlace su AdGuard Home."
|
||||
"description": "Configure su instancia de AdGuard Home para permitir la supervisi\u00f3n y el control."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
"username": "Usuario",
|
||||
"verify_ssl": "AdGuard Home utiliza un certificado apropiado"
|
||||
},
|
||||
"description": "Configure su instancia de AdGuard Home para permitir la supervisi\u00f3n y el control.",
|
||||
"title": "Enlace su AdGuard Home."
|
||||
"description": "Configure su instancia de AdGuard Home para permitir la supervisi\u00f3n y el control."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
"username": "Nom d'utilisateur",
|
||||
"verify_ssl": "AdGuard Home utilise un certificat appropri\u00e9"
|
||||
},
|
||||
"description": "Configurez votre instance AdGuard Home pour permettre la surveillance et le contr\u00f4le.",
|
||||
"title": "Liez votre AdGuard Home."
|
||||
"description": "Configurez votre instance AdGuard Home pour permettre la surveillance et le contr\u00f4le."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "Hoszt",
|
||||
"password": "Jelsz\u00f3",
|
||||
"port": "Port",
|
||||
"username": "Felhaszn\u00e1l\u00f3n\u00e9v"
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
"username": "Nome utente",
|
||||
"verify_ssl": "AdGuard Home utilizza un certificato appropriato"
|
||||
},
|
||||
"description": "Configura l'istanza di AdGuard Home per consentire il monitoraggio e il controllo.",
|
||||
"title": "Collega la tua AdGuard Home."
|
||||
"description": "Configura l'istanza di AdGuard Home per consentire il monitoraggio e il controllo."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
"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"
|
||||
},
|
||||
"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"
|
||||
"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."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
"username": "Benotzernumm",
|
||||
"verify_ssl": "AdGuard Home benotzt een eegenen Zertifikat"
|
||||
},
|
||||
"description": "Konfigur\u00e9iert \u00e4r AdGuard Home Instanz fir d'Iwwerwaachung an d'Kontroll z'erlaben.",
|
||||
"title": "Verbannt \u00e4ren AdGuard Home"
|
||||
"description": "Konfigur\u00e9iert \u00e4r AdGuard Home Instanz fir d'Iwwerwaachung an d'Kontroll z'erlaben."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,7 @@
|
|||
"username": "Gebruikersnaam",
|
||||
"verify_ssl": "AdGuard Home maakt gebruik van een goed certificaat"
|
||||
},
|
||||
"description": "Stel uw AdGuard Home-instantie in om toezicht en controle mogelijk te maken.",
|
||||
"title": "Link uw AdGuard Home."
|
||||
"description": "Stel uw AdGuard Home-instantie in om toezicht en controle mogelijk te maken."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,7 @@
|
|||
"ssl": "AdGuard Hjem bruker et SSL-sertifikat",
|
||||
"verify_ssl": "AdGuard Home bruker et riktig sertifikat"
|
||||
},
|
||||
"description": "Sett opp din AdGuard Hjem instans for \u00e5 tillate overv\u00e5king og kontroll.",
|
||||
"title": "Koble til ditt AdGuard Hjem."
|
||||
"description": "Sett opp din AdGuard Hjem instans for \u00e5 tillate overv\u00e5king og kontroll."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"single_instance_allowed": "Dozwolona jest tylko jedna konfiguracja AdGuard Home."
|
||||
},
|
||||
"error": {
|
||||
"connection_error": "[%key_id:common::config_flow::error::cannot_connect%]"
|
||||
"connection_error": "Nie mo\u017cna nawi\u0105za\u0107 po\u0142\u0105czenia."
|
||||
},
|
||||
"step": {
|
||||
"hassio_confirm": {
|
||||
|
@ -16,15 +16,14 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "[%key_id:common::config_flow::data::host%]",
|
||||
"password": "[%key_id:common::config_flow::data::password%]",
|
||||
"port": "[%key_id:common::config_flow::data::port%]",
|
||||
"host": "Nazwa hosta lub adres IP",
|
||||
"password": "Has\u0142o",
|
||||
"port": "Port",
|
||||
"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."
|
||||
},
|
||||
"description": "Skonfiguruj instancj\u0119 AdGuard Home, aby umo\u017cliwi\u0107 monitorowanie i kontrol\u0119.",
|
||||
"title": "Po\u0142\u0105cz AdGuard Home"
|
||||
"description": "Skonfiguruj instancj\u0119 AdGuard Home, aby umo\u017cliwi\u0107 monitorowanie i kontrol\u0119."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,7 @@
|
|||
"username": "Nome de usu\u00e1rio",
|
||||
"verify_ssl": "O AdGuard Home usa um certificado apropriado"
|
||||
},
|
||||
"description": "Configure sua inst\u00e2ncia do AdGuard Home para permitir o monitoramento e o controle.",
|
||||
"title": "Vincule o seu AdGuard Home."
|
||||
"description": "Configure sua inst\u00e2ncia do AdGuard Home para permitir o monitoramento e o controle."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
"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"
|
||||
},
|
||||
"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"
|
||||
"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."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
"username": "Uporabni\u0161ko ime",
|
||||
"verify_ssl": "AdGuard Home uporablja ustrezen certifikat"
|
||||
},
|
||||
"description": "Nastavite primerek AdGuard Home, da omogo\u010dite spremljanje in nadzor.",
|
||||
"title": "Pove\u017eite svoj AdGuard Home."
|
||||
"description": "Nastavite primerek AdGuard Home, da omogo\u010dite spremljanje in nadzor."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,7 @@
|
|||
"username": "Anv\u00e4ndarnamn",
|
||||
"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.",
|
||||
"title": "L\u00e4nka din AdGuard Home."
|
||||
"description": "St\u00e4ll in din AdGuard Home-instans f\u00f6r att till\u00e5ta \u00f6vervakning och kontroll."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@
|
|||
"username": "\u4f7f\u7528\u8005\u540d\u7a31",
|
||||
"verify_ssl": "AdGuard Home \u4f7f\u7528\u5c0d\u61c9\u8a8d\u8b49"
|
||||
},
|
||||
"description": "\u8a2d\u5b9a AdGuard Home \u4ee5\u9032\u884c\u76e3\u63a7\u3002",
|
||||
"title": "\u9023\u7d50 AdGuard Home\u3002"
|
||||
"description": "\u8a2d\u5b9a AdGuard Home \u4ee5\u9032\u884c\u76e3\u63a7\u3002"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
|
@ -12,7 +12,8 @@
|
|||
"data": {
|
||||
"host": "H\u00f4te",
|
||||
"port": "Port"
|
||||
}
|
||||
},
|
||||
"title": "Configurer l'agent DVR"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"latitude": "Leveysaste",
|
||||
"longitude": "Pituusaste"
|
||||
"host": "Hoszt",
|
||||
"port": "Port"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "[%key_id:common::config_flow::abort::already_configured_device%]"
|
||||
"already_configured": "Urz\u0105dzenie jest ju\u017c skonfigurowane."
|
||||
},
|
||||
"error": {
|
||||
"already_in_progress": "Konfiguracja urz\u0105dzenia jest ju\u017c w toku.",
|
||||
|
@ -10,8 +10,8 @@
|
|||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"host": "[%key_id:common::config_flow::data::host%]",
|
||||
"port": "[%key_id:common::config_flow::data::port%]"
|
||||
"host": "Nazwa hosta lub adres IP",
|
||||
"port": "Port"
|
||||
},
|
||||
"title": "Konfiguracja Agent DVR"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"config": {
|
||||
"error": {
|
||||
"device_unavailable": "O dispositivo n\u00e3o est\u00e1 dispon\u00edvel"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,7 +10,7 @@
|
|||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Clau API d'Airly",
|
||||
"api_key": "Clau API",
|
||||
"latitude": "Latitud",
|
||||
"longitude": "Longitud",
|
||||
"name": "Nom de la integraci\u00f3"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Airly API kulcs",
|
||||
"api_key": "API kulcs",
|
||||
"latitude": "Sz\u00e9less\u00e9g",
|
||||
"longitude": "Hossz\u00fas\u00e1g",
|
||||
"name": "Az integr\u00e1ci\u00f3 neve"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Chiave API Airly",
|
||||
"api_key": "Chiave API",
|
||||
"latitude": "Latitudine",
|
||||
"longitude": "Logitudine",
|
||||
"name": "Nome dell'integrazione"
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "[%key_id:common::config_flow::data::api_key%] Airly",
|
||||
"api_key": "Klucz API",
|
||||
"latitude": "Szeroko\u015b\u0107 geograficzna",
|
||||
"longitude": "D\u0142ugo\u015b\u0107 geograficzna",
|
||||
"name": "Nazwa integracji"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "Aquesta clau API ja est\u00e0 sent utilitzada."
|
||||
"already_configured": "Aquestes coordenades o Node/Pro ID ja estan registrades."
|
||||
},
|
||||
"error": {
|
||||
"general_error": "S'ha produ\u00eft un error desconegut.",
|
||||
|
@ -21,21 +21,18 @@
|
|||
"node_pro": {
|
||||
"data": {
|
||||
"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.",
|
||||
"title": "Configuraci\u00f3 d'AirVisual Node/Pro"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Clau API",
|
||||
"cloud_api": "Ubicaci\u00f3 geogr\u00e0fica",
|
||||
"latitude": "Latitud",
|
||||
"longitude": "Longitud",
|
||||
"node_pro": "AirVisual Node Pro",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +43,6 @@
|
|||
"data": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,10 +27,7 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API-Schl\u00fcssel",
|
||||
"cloud_api": "Geografische Position",
|
||||
"latitude": "Breitengrad",
|
||||
"longitude": "L\u00e4ngengrad",
|
||||
"node_pro": "AirVisual Node Pro",
|
||||
"type": "Integrationstyp"
|
||||
},
|
||||
|
@ -45,7 +42,6 @@
|
|||
"data": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,7 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API Key",
|
||||
"cloud_api": "Geographical Location",
|
||||
"latitude": "Latitude",
|
||||
"longitude": "Longitude",
|
||||
"node_pro": "AirVisual Node Pro",
|
||||
"type": "Integration Type"
|
||||
},
|
||||
|
@ -46,7 +43,6 @@
|
|||
"data": {
|
||||
"show_on_map": "Show monitored geography on the map"
|
||||
},
|
||||
"description": "Set various options for the AirVisual integration.",
|
||||
"title": "Configure AirVisual"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,11 +5,13 @@
|
|||
},
|
||||
"error": {
|
||||
"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."
|
||||
},
|
||||
"step": {
|
||||
"geography": {
|
||||
"data": {
|
||||
"api_key": "Clave API",
|
||||
"latitude": "Latitud",
|
||||
"longitude": "Longitud"
|
||||
},
|
||||
|
@ -26,10 +28,7 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Clave API",
|
||||
"cloud_api": "Localizaci\u00f3n geogr\u00e1fica",
|
||||
"latitude": "Latitud",
|
||||
"longitude": "Longitud",
|
||||
"node_pro": "AirVisual Node Pro",
|
||||
"type": "Tipo de integraci\u00f3n"
|
||||
},
|
||||
|
@ -44,7 +43,6 @@
|
|||
"data": {
|
||||
"show_on_map": "Mostrar geograf\u00eda monitoreada en el mapa"
|
||||
},
|
||||
"description": "Establezca varias opciones para la integraci\u00f3n de AirVisual.",
|
||||
"title": "Configurar AirVisual"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,21 +21,18 @@
|
|||
"node_pro": {
|
||||
"data": {
|
||||
"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.",
|
||||
"title": "Configurar un AirVisual Node/Pro"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Clave API",
|
||||
"cloud_api": "Ubicaci\u00f3n Geogr\u00e1fica",
|
||||
"latitude": "Latitud",
|
||||
"longitude": "Longitud",
|
||||
"node_pro": "AirVisual Node Pro",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
@ -46,7 +43,6 @@
|
|||
"data": {
|
||||
"show_on_map": "Mostrar geograf\u00eda monitorizada en el mapa"
|
||||
},
|
||||
"description": "Ajustar varias opciones para la integraci\u00f3n de AirVisual.",
|
||||
"title": "Configurar AirVisual"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,7 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Cl\u00e9 API",
|
||||
"cloud_api": "Localisation g\u00e9ographique",
|
||||
"latitude": "Latitude",
|
||||
"longitude": "Longitude",
|
||||
"node_pro": "AirVisual Node Pro",
|
||||
"type": "Type d'int\u00e9gration"
|
||||
},
|
||||
|
@ -46,7 +43,6 @@
|
|||
"data": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,15 @@
|
|||
"step": {
|
||||
"geography": {
|
||||
"data": {
|
||||
"api_key": "API Kulcs",
|
||||
"api_key": "API kulcs",
|
||||
"latitude": "Sz\u00e9less\u00e9g",
|
||||
"longitude": "Hossz\u00fas\u00e1g"
|
||||
}
|
||||
},
|
||||
"node_pro": {
|
||||
"data": {
|
||||
"password": "Jelsz\u00f3"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,17 +21,14 @@
|
|||
"node_pro": {
|
||||
"data": {
|
||||
"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.",
|
||||
"title": "Configurare un AirVisual Node/Pro"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "Chiave API",
|
||||
"cloud_api": "Posizione geografica",
|
||||
"latitude": "Latitudine",
|
||||
"longitude": "Logitudine",
|
||||
"node_pro": "AirVisual Node Pro",
|
||||
"type": "Tipo di integrazione"
|
||||
},
|
||||
|
@ -46,7 +43,6 @@
|
|||
"data": {
|
||||
"show_on_map": "Mostra l'area geografica monitorata sulla mappa"
|
||||
},
|
||||
"description": "Impostare varie opzioni per l'integrazione AirVisual.",
|
||||
"title": "Configurare AirVisual"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,7 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API \ud0a4",
|
||||
"cloud_api": "\uc9c0\ub9ac\uc801 \uc704\uce58",
|
||||
"latitude": "\uc704\ub3c4",
|
||||
"longitude": "\uacbd\ub3c4",
|
||||
"node_pro": "AirVisual Node Pro",
|
||||
"type": "\uc5f0\ub3d9 \uc720\ud615"
|
||||
},
|
||||
|
@ -46,7 +43,6 @@
|
|||
"data": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,7 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API Schl\u00ebssel",
|
||||
"cloud_api": "Geografesche Standuert",
|
||||
"latitude": "Breedegrad",
|
||||
"longitude": "L\u00e4ngegrad",
|
||||
"node_pro": "Airvisual Node Pro",
|
||||
"type": "Typ vun der Integratioun"
|
||||
},
|
||||
|
@ -46,7 +43,6 @@
|
|||
"data": {
|
||||
"show_on_map": "Iwwerwaachte Geografie op der Kaart uweisen"
|
||||
},
|
||||
"description": "Verschidden Optioune fir d'AirVisual Integratioun d\u00e9fin\u00e9ieren.",
|
||||
"title": "Airvisual ariichten"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,10 +26,7 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API-sleutel",
|
||||
"cloud_api": "Geografische ligging",
|
||||
"latitude": "Breedtegraad",
|
||||
"longitude": "Lengtegraad",
|
||||
"node_pro": "AirVisual Node Pro",
|
||||
"type": "Integratietype"
|
||||
},
|
||||
|
@ -44,7 +41,6 @@
|
|||
"data": {
|
||||
"show_on_map": "Toon gecontroleerde geografie op de kaart"
|
||||
},
|
||||
"description": "Stel verschillende opties in voor de AirVisual-integratie.",
|
||||
"title": "Configureer AirVisual"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,7 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API-n\u00f8kkel",
|
||||
"cloud_api": "Geografisk plassering",
|
||||
"latitude": "Breddegrad",
|
||||
"longitude": "Lengdegrad",
|
||||
"node_pro": "",
|
||||
"type": "Integrasjonstype"
|
||||
},
|
||||
|
@ -46,7 +43,6 @@
|
|||
"data": {
|
||||
"show_on_map": "Vis overv\u00e5ket geografi p\u00e5 kartet"
|
||||
},
|
||||
"description": "Angi forskjellige alternativer for AirVisual-integrasjonen.",
|
||||
"title": "Konfigurer AirVisual"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
"already_configured": "Ten klucz API jest ju\u017c w u\u017cyciu."
|
||||
},
|
||||
"error": {
|
||||
"general_error": "[%key_id:common::config_flow::error::unknown%]",
|
||||
"general_error": "Nieoczekiwany b\u0142\u0105d.",
|
||||
"invalid_api_key": "Nieprawid\u0142owy klucz API.",
|
||||
"unable_to_connect": "Nie mo\u017cna po\u0142\u0105czy\u0107 si\u0119 z jednostk\u0105 Node/Pro."
|
||||
},
|
||||
"step": {
|
||||
"geography": {
|
||||
"data": {
|
||||
"api_key": "[%key_id:common::config_flow::data::api_key%]",
|
||||
"api_key": "Klucz API",
|
||||
"latitude": "Szeroko\u015b\u0107 geograficzna",
|
||||
"longitude": "D\u0142ugo\u015b\u0107 geograficzna"
|
||||
},
|
||||
|
@ -20,18 +20,15 @@
|
|||
},
|
||||
"node_pro": {
|
||||
"data": {
|
||||
"ip_address": "[%key_id:common::config_flow::data::host%]",
|
||||
"password": "[%key_id:common::config_flow::data::password%] jednostki"
|
||||
"ip_address": "Nazwa hosta lub adres IP",
|
||||
"password": "Has\u0142o"
|
||||
},
|
||||
"description": "Monitoruj jednostk\u0119 AirVisual. Has\u0142o mo\u017cna odzyska\u0107 z interfejsu u\u017cytkownika urz\u0105dzenia.",
|
||||
"title": "Konfiguracja AirVisual Node/Pro"
|
||||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "[%key_id:common::config_flow::data::api_key%]",
|
||||
"cloud_api": "Lokalizacja geograficzna",
|
||||
"latitude": "Szeroko\u015b\u0107 geograficzna",
|
||||
"longitude": "D\u0142ugo\u015b\u0107 geograficzna",
|
||||
"node_pro": "AirVisual Node Pro",
|
||||
"type": "Typ integracji"
|
||||
},
|
||||
|
@ -46,7 +43,6 @@
|
|||
"data": {
|
||||
"show_on_map": "Wy\u015bwietlaj encje na mapie"
|
||||
},
|
||||
"description": "Konfiguracja opcji integracji AirVisual.",
|
||||
"title": "Konfiguracja AirVisual"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,10 +28,7 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "\u041a\u043b\u044e\u0447 API",
|
||||
"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",
|
||||
"type": "\u0422\u0438\u043f \u0438\u043d\u0442\u0435\u0433\u0440\u0430\u0446\u0438\u0438"
|
||||
},
|
||||
|
@ -46,7 +43,6 @@
|
|||
"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"
|
||||
},
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,10 +28,7 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API Klju\u010d",
|
||||
"cloud_api": "Geografska lokacija",
|
||||
"latitude": "Zemljepisna \u0161irina",
|
||||
"longitude": "Zemljepisna dol\u017eina",
|
||||
"node_pro": "AirVisual Node Pro",
|
||||
"type": "Vrsta integracije"
|
||||
},
|
||||
|
@ -46,7 +43,6 @@
|
|||
"data": {
|
||||
"show_on_map": "Prika\u017ei nadzorovano obmo\u010dje na zemljevidu"
|
||||
},
|
||||
"description": "Nastavite razli\u010dne mo\u017enosti za integracijo AirVisual.",
|
||||
"title": "Nastavite AirVisual"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,10 +18,7 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API-nyckel",
|
||||
"cloud_api": "Geografisk Plats",
|
||||
"latitude": "Latitud",
|
||||
"longitude": "Longitud",
|
||||
"type": "Integrationstyp"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
},
|
||||
"error": {
|
||||
"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"
|
||||
},
|
||||
"step": {
|
||||
|
@ -28,10 +28,7 @@
|
|||
},
|
||||
"user": {
|
||||
"data": {
|
||||
"api_key": "API \u5bc6\u9470",
|
||||
"cloud_api": "\u5730\u7406\u5ea7\u6a19",
|
||||
"latitude": "\u7def\u5ea6",
|
||||
"longitude": "\u7d93\u5ea6",
|
||||
"node_pro": "AirVisual Node Pro",
|
||||
"type": "\u6574\u5408\u985e\u578b"
|
||||
},
|
||||
|
@ -46,7 +43,6 @@
|
|||
"data": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,13 +24,13 @@
|
|||
},
|
||||
"state": {
|
||||
"_": {
|
||||
"armed": "Armado",
|
||||
"armed": "Armada",
|
||||
"armed_away": "Armada ausente",
|
||||
"armed_custom_bypass": "Armada personalizada",
|
||||
"armed_home": "Armada en casa",
|
||||
"armed_night": "Armada noche",
|
||||
"arming": "Armando",
|
||||
"disarmed": "Desarmado",
|
||||
"disarmed": "Desarmada",
|
||||
"disarming": "Desarmando",
|
||||
"pending": "Pendiente",
|
||||
"triggered": "Disparada"
|
||||
|
|
|
@ -7,6 +7,13 @@
|
|||
"disarm": "Desarmar {entity_name}",
|
||||
"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": {
|
||||
"armed_away": "{entity_name} armado modo longe",
|
||||
"armed_home": "{entity_name} armadado modo casa",
|
||||
|
|
|
@ -3,15 +3,13 @@ import logging
|
|||
|
||||
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.helpers import config_validation as cv, entityfilter
|
||||
|
||||
from . import flash_briefings, intent, smart_home_http
|
||||
from .const import (
|
||||
CONF_AUDIO,
|
||||
CONF_CLIENT_ID,
|
||||
CONF_CLIENT_SECRET,
|
||||
CONF_DESCRIPTION,
|
||||
CONF_DISPLAY_CATEGORIES,
|
||||
CONF_DISPLAY_URL,
|
||||
|
|
|
@ -7,7 +7,7 @@ import logging
|
|||
import aiohttp
|
||||
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.helpers import aiohttp_client
|
||||
from homeassistant.util import dt
|
||||
|
@ -48,8 +48,8 @@ class Auth:
|
|||
lwa_params = {
|
||||
"grant_type": "authorization_code",
|
||||
"code": accept_grant_code,
|
||||
"client_id": self.client_id,
|
||||
"client_secret": self.client_secret,
|
||||
CONF_CLIENT_ID: self.client_id,
|
||||
CONF_CLIENT_SECRET: self.client_secret,
|
||||
}
|
||||
_LOGGER.debug(
|
||||
"Calling LWA to get the access token (first time), with: %s",
|
||||
|
@ -80,8 +80,8 @@ class Auth:
|
|||
lwa_params = {
|
||||
"grant_type": "refresh_token",
|
||||
"refresh_token": self._prefs[STORAGE_REFRESH_TOKEN],
|
||||
"client_id": self.client_id,
|
||||
"client_secret": self.client_secret,
|
||||
CONF_CLIENT_ID: self.client_id,
|
||||
CONF_CLIENT_SECRET: self.client_secret,
|
||||
}
|
||||
|
||||
_LOGGER.debug("Calling LWA to refresh the access token.")
|
||||
|
|
|
@ -1661,7 +1661,21 @@ class AlexaDoorbellEventSource(AlexaCapability):
|
|||
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):
|
||||
"""Return the Alexa API name of this interface."""
|
||||
|
@ -1789,6 +1803,13 @@ class AlexaEqualizerController(AlexaCapability):
|
|||
"""
|
||||
|
||||
supported_locales = {"en-US"}
|
||||
VALID_SOUND_MODES = {
|
||||
"MOVIE",
|
||||
"MUSIC",
|
||||
"NIGHT",
|
||||
"SPORT",
|
||||
"TV",
|
||||
}
|
||||
|
||||
def name(self):
|
||||
"""Return the Alexa API name of this interface."""
|
||||
|
@ -1807,35 +1828,34 @@ class AlexaEqualizerController(AlexaCapability):
|
|||
raise UnsupportedProperty(name)
|
||||
|
||||
sound_mode = self.entity.attributes.get(media_player.ATTR_SOUND_MODE)
|
||||
if sound_mode and sound_mode.upper() in (
|
||||
"MOVIE",
|
||||
"MUSIC",
|
||||
"NIGHT",
|
||||
"SPORT",
|
||||
"TV",
|
||||
):
|
||||
if sound_mode and sound_mode.upper() in self.VALID_SOUND_MODES:
|
||||
return sound_mode.upper()
|
||||
|
||||
return None
|
||||
|
||||
def configurations(self):
|
||||
"""Return the sound modes supported in the configurations object.
|
||||
|
||||
Valid Values for modes are: MOVIE, MUSIC, NIGHT, SPORT, TV.
|
||||
"""
|
||||
"""Return the sound modes supported in the configurations object."""
|
||||
configurations = None
|
||||
sound_mode_list = self.entity.attributes.get(media_player.ATTR_SOUND_MODE_LIST)
|
||||
if sound_mode_list:
|
||||
supported_sound_modes = [
|
||||
{"name": sound_mode.upper()}
|
||||
for sound_mode in sound_mode_list
|
||||
if sound_mode.upper() in ("MOVIE", "MUSIC", "NIGHT", "SPORT", "TV")
|
||||
]
|
||||
|
||||
supported_sound_modes = self.get_valid_inputs(
|
||||
self.entity.attributes.get(media_player.ATTR_SOUND_MODE_LIST, [])
|
||||
)
|
||||
if supported_sound_modes:
|
||||
configurations = {"modes": {"supported": supported_sound_modes}}
|
||||
|
||||
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):
|
||||
"""Implements Alexa.TimeHoldController.
|
||||
|
|
|
@ -18,8 +18,6 @@ CONF_DISPLAY_URL = "display_url"
|
|||
CONF_FILTER = "filter"
|
||||
CONF_ENTITY_CONFIG = "entity_config"
|
||||
CONF_ENDPOINT = "endpoint"
|
||||
CONF_CLIENT_ID = "client_id"
|
||||
CONF_CLIENT_SECRET = "client_secret"
|
||||
CONF_LOCALE = "locale"
|
||||
|
||||
ATTR_UID = "uid"
|
||||
|
@ -126,6 +124,8 @@ class Inputs:
|
|||
"""
|
||||
|
||||
VALID_SOURCE_NAME_MAP = {
|
||||
"antenna": "TUNER",
|
||||
"antennatv": "TUNER",
|
||||
"aux": "AUX 1",
|
||||
"aux1": "AUX 1",
|
||||
"aux2": "AUX 2",
|
||||
|
@ -135,6 +135,7 @@ class Inputs:
|
|||
"aux6": "AUX 6",
|
||||
"aux7": "AUX 7",
|
||||
"bluray": "BLURAY",
|
||||
"blurayplayer": "BLURAY",
|
||||
"cable": "CABLE",
|
||||
"cd": "CD",
|
||||
"coax": "COAX 1",
|
||||
|
@ -186,6 +187,7 @@ class Inputs:
|
|||
"playstation": "PLAYSTATION",
|
||||
"playstation3": "PLAYSTATION 3",
|
||||
"playstation4": "PLAYSTATION 4",
|
||||
"rokumediaplayer": "MEDIA PLAYER",
|
||||
"satellite": "SATELLITE",
|
||||
"satellitetv": "SATELLITE",
|
||||
"smartcast": "SMARTCAST",
|
||||
|
|
|
@ -547,7 +547,11 @@ class MediaPlayerCapabilities(AlexaEntity):
|
|||
yield AlexaChannelController(self.entity)
|
||||
|
||||
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 Alexa(self.hass)
|
||||
|
|
|
@ -40,6 +40,16 @@ def async_setup(hass):
|
|||
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):
|
||||
"""When an unknown Alexa request is passed in."""
|
||||
|
||||
|
|
|
@ -3,17 +3,11 @@ import logging
|
|||
|
||||
from homeassistant import core
|
||||
from homeassistant.components.http.view import HomeAssistantView
|
||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
||||
|
||||
from .auth import Auth
|
||||
from .config import AbstractConfig
|
||||
from .const import (
|
||||
CONF_CLIENT_ID,
|
||||
CONF_CLIENT_SECRET,
|
||||
CONF_ENDPOINT,
|
||||
CONF_ENTITY_CONFIG,
|
||||
CONF_FILTER,
|
||||
CONF_LOCALE,
|
||||
)
|
||||
from .const import CONF_ENDPOINT, CONF_ENTITY_CONFIG, CONF_FILTER, CONF_LOCALE
|
||||
from .smart_home import async_handle_message
|
||||
from .state_report import async_enable_proactive_mode
|
||||
|
||||
|
|
|
@ -13,7 +13,13 @@ import voluptuous as vol
|
|||
from homeassistant import config_entries
|
||||
from homeassistant.auth.const import GROUP_ID_ADMIN
|
||||
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.exceptions import ConfigEntryNotReady
|
||||
from homeassistant.helpers import (
|
||||
|
@ -29,9 +35,6 @@ from homeassistant.helpers import (
|
|||
from . import config_flow
|
||||
from .const import DOMAIN, TYPE_LOCAL, TYPE_OAUTH2
|
||||
|
||||
CONF_CLIENT_ID = "client_id"
|
||||
CONF_CLIENT_SECRET = "client_secret"
|
||||
|
||||
STORAGE_VERSION = 1
|
||||
STORAGE_KEY = DOMAIN
|
||||
|
||||
|
|
|
@ -7,11 +7,11 @@
|
|||
},
|
||||
"step": {
|
||||
"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"
|
||||
},
|
||||
"pick_implementation": {
|
||||
"title": "[%key_id:common::config_flow::title::oauth2_pick_implementation%]"
|
||||
"title": "Wybierz metod\u0119 uwierzytelniania"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,10 +3,11 @@ import logging
|
|||
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
|
||||
from . import config_flow
|
||||
from .const import CONF_CLIENT_ID, CONF_CLIENT_SECRET, DOMAIN
|
||||
from .const import DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
|
|
@ -11,14 +11,18 @@ from homeassistant.components.climate.const import (
|
|||
HVAC_MODE_OFF,
|
||||
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.aiohttp_client import async_get_clientsession
|
||||
|
||||
from .const import (
|
||||
ATTR_VALUE,
|
||||
CONF_CLIENT_ID,
|
||||
CONF_CLIENT_SECRET,
|
||||
DOMAIN,
|
||||
SERVICE_COMFORT_FEEDBACK,
|
||||
SERVICE_COMFORT_MODE,
|
||||
|
|
|
@ -5,6 +5,7 @@ import ambiclimate
|
|||
|
||||
from homeassistant import config_entries
|
||||
from homeassistant.components.http import HomeAssistantView
|
||||
from homeassistant.const import CONF_CLIENT_ID, CONF_CLIENT_SECRET
|
||||
from homeassistant.core import callback
|
||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
from homeassistant.helpers.network import get_url
|
||||
|
@ -12,8 +13,6 @@ from homeassistant.helpers.network import get_url
|
|||
from .const import (
|
||||
AUTH_CALLBACK_NAME,
|
||||
AUTH_CALLBACK_PATH,
|
||||
CONF_CLIENT_ID,
|
||||
CONF_CLIENT_SECRET,
|
||||
DOMAIN,
|
||||
STORAGE_KEY,
|
||||
STORAGE_VERSION,
|
||||
|
|
|
@ -1,12 +1,13 @@
|
|||
"""Constants used by the Ambiclimate component."""
|
||||
|
||||
ATTR_VALUE = "value"
|
||||
CONF_CLIENT_ID = "client_id"
|
||||
CONF_CLIENT_SECRET = "client_secret"
|
||||
DOMAIN = "ambiclimate"
|
||||
|
||||
ATTR_VALUE = "value"
|
||||
|
||||
SERVICE_COMFORT_FEEDBACK = "send_comfort_feedback"
|
||||
SERVICE_COMFORT_MODE = "set_comfort_mode"
|
||||
SERVICE_TEMPERATURE_MODE = "set_temperature_mode"
|
||||
|
||||
STORAGE_KEY = "ambiclimate_auth"
|
||||
STORAGE_VERSION = 1
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
},
|
||||
"step": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
},
|
||||
"step": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
},
|
||||
"step": {
|
||||
"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"
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue