Merge pull request #23353 from home-assistant/rc

0.92.0
This commit is contained in:
Paulus Schoutsen 2019-04-24 13:37:44 -07:00 committed by GitHub
commit 8ae2ce2299
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2713 changed files with 32282 additions and 13299 deletions

View File

@ -57,6 +57,7 @@ commands:
<<# parameters.all >>pip install -q --progress-bar off -r requirements_all.txt -c homeassistant/package_constraints.txt<</ parameters.all>>
<<# parameters.test >>pip install -q --progress-bar off -r requirements_test.txt -c homeassistant/package_constraints.txt<</ parameters.test>>
<<# parameters.test_all >>pip install -q --progress-bar off -r requirements_test_all.txt -c homeassistant/package_constraints.txt<</ parameters.test_all>>
no_output_timeout: 15m
- save_cache:
paths:
- ./venv
@ -99,6 +100,13 @@ jobs:
mypy $TYPING_FILES
- install
- run:
name: validate manifests
command: |
. venv/bin/activate
python -m script.hassfest validate
- run:
name: run gen_requirements_all
command: |
@ -139,6 +147,7 @@ jobs:
. venv/bin/activate
PYFILES=$(circleci tests glob "homeassistant/**/*.py" | circleci tests split)
pylint ${PYFILES}
no_output_timeout: 15m
pre-test:
parameters:
@ -173,13 +182,14 @@ jobs:
- install
- run:
name: run tests
name: run tests with code coverage
command: |
. venv/bin/activate
CC_SWITCH="--cov --cov-report="
TESTFILES=$(circleci tests glob "tests/**/test_*.py" | circleci tests split --split-by=timings)
if [ -z "$CODE_COVERAGE" ]; then CC_SWITCH=""; else CC_SWITCH="--cov --cov-report html:htmlcov"; fi
pytest --timeout=9 --duration=10 --junitxml=test-reports/homeassistant/results.xml -qq -o junit_family=xunit2 -o junit_suite_name=homeassistant -o console_output_style=count -p no:sugar $CC_SWITCH -- ${TESTFILES}
pytest --timeout=9 --durations=10 --junitxml=test-reports/homeassistant/results.xml -qq -o junit_family=xunit2 -o junit_suite_name=homeassistant -o console_output_style=count -p no:sugar $CC_SWITCH -- ${TESTFILES}
script/check_dirty
codecov
- store_test_results:
path: test-reports

15
.codecov.yml Normal file
View File

@ -0,0 +1,15 @@
codecov:
branch: dev
coverage:
status:
project:
default:
target: 90
threshold: 0.09
notify:
# Notify codecov room in Discord. The webhook URL (encrypted below) ends in /slack which is why we configure a Slack notification.
slack:
default:
url: "secret:TgWDUM4Jw0w7wMJxuxNF/yhSOHglIo1fGwInJnRLEVPy2P2aLimkoK1mtKCowH5TFw+baUXVXT3eAqefbdvIuM8BjRR4aRji95C6CYyD0QHy4N8i7nn1SQkWDPpS8IthYTg07rUDF7s5guurkKv2RrgoCdnnqjAMSzHoExMOF7xUmblMdhBTWJgBpWEhASJy85w/xxjlsE1xoTkzeJu9Q67pTXtRcn+5kb5/vIzPSYg="
comment:
require_changes: yes

View File

@ -21,14 +21,15 @@ omit =
homeassistant/components/alarmdecoder/*
homeassistant/components/alarmdotcom/alarm_control_panel.py
homeassistant/components/alpha_vantage/sensor.py
homeassistant/components/amazon_polly/tts.py
homeassistant/components/ambient_station/*
homeassistant/components/amcrest/*
homeassistant/components/ampio/*
homeassistant/components/android_ip_webcam/*
homeassistant/components/androidtv/*
homeassistant/components/anel_pwrctrl/switch.py
homeassistant/components/anthemav/media_player.py
homeassistant/components/apcupsd/*
homeassistant/components/apiai/*
homeassistant/components/apple_tv/*
homeassistant/components/aqualogic/*
homeassistant/components/aquostv/media_player.py
@ -45,9 +46,7 @@ omit =
homeassistant/components/august/*
homeassistant/components/automatic/device_tracker.py
homeassistant/components/avion/light.py
homeassistant/components/aws_lambda/notify.py
homeassistant/components/aws_sns/notify.py
homeassistant/components/aws_sqs/notify.py
homeassistant/components/baidu/tts.py
homeassistant/components/bbb_gpio/*
homeassistant/components/bbox/device_tracker.py
homeassistant/components/bbox/sensor.py
@ -64,6 +63,7 @@ omit =
homeassistant/components/bme280/sensor.py
homeassistant/components/bme680/sensor.py
homeassistant/components/bmw_connected_drive/*
homeassistant/components/bom/camera.py
homeassistant/components/bom/sensor.py
homeassistant/components/bom/weather.py
homeassistant/components/braviatv/media_player.py
@ -84,6 +84,7 @@ omit =
homeassistant/components/channels/media_player.py
homeassistant/components/cisco_ios/device_tracker.py
homeassistant/components/cisco_mobility_express/device_tracker.py
homeassistant/components/cisco_webex_teams/notify.py
homeassistant/components/ciscospark/notify.py
homeassistant/components/citybikes/sensor.py
homeassistant/components/clementine/media_player.py
@ -92,6 +93,7 @@ omit =
homeassistant/components/clicksend_tts/notify.py
homeassistant/components/cloudflare/*
homeassistant/components/cmus/media_player.py
homeassistant/components/co2signal/*
homeassistant/components/coinbase/*
homeassistant/components/comed_hourly_pricing/sensor.py
homeassistant/components/comfoconnect/*
@ -125,7 +127,6 @@ omit =
homeassistant/components/dlink/switch.py
homeassistant/components/dlna_dmr/media_player.py
homeassistant/components/dnsip/sensor.py
homeassistant/components/domain_expiry/sensor.py
homeassistant/components/dominos/*
homeassistant/components/doorbird/*
homeassistant/components/dovado/*
@ -161,9 +162,12 @@ omit =
homeassistant/components/envisalink/*
homeassistant/components/ephember/climate.py
homeassistant/components/epson/media_player.py
homeassistant/components/epsonworkforce/sensor.py
homeassistant/components/eq3btsmart/climate.py
homeassistant/components/esphome/__init__.py
homeassistant/components/esphome/binary_sensor.py
homeassistant/components/esphome/camera.py
homeassistant/components/esphome/climate.py
homeassistant/components/esphome/cover.py
homeassistant/components/esphome/fan.py
homeassistant/components/esphome/light.py
@ -203,6 +207,7 @@ omit =
homeassistant/components/futurenow/light.py
homeassistant/components/garadget/cover.py
homeassistant/components/gc100/*
homeassistant/components/geniushub/*
homeassistant/components/gearbest/sensor.py
homeassistant/components/geizhals/sensor.py
homeassistant/components/github/sensor.py
@ -266,13 +271,10 @@ omit =
homeassistant/components/ifttt/*
homeassistant/components/iglo/light.py
homeassistant/components/ihc/*
homeassistant/components/iliad_italy/sensor.py
homeassistant/components/imap/sensor.py
homeassistant/components/imap_email_content/sensor.py
homeassistant/components/influxdb/sensor.py
homeassistant/components/insteon/*
homeassistant/components/insteon_local/*
homeassistant/components/insteon_plm/*
homeassistant/components/ios/*
homeassistant/components/iota/*
homeassistant/components/iperf3/*
@ -318,7 +320,10 @@ omit =
homeassistant/components/liveboxplaytv/media_player.py
homeassistant/components/llamalab_automate/notify.py
homeassistant/components/lockitron/lock.py
homeassistant/components/logi_circle/*
homeassistant/components/logi_circle/__init__.py
homeassistant/components/logi_circle/camera.py
homeassistant/components/logi_circle/const.py
homeassistant/components/logi_circle/sensor.py
homeassistant/components/london_underground/sensor.py
homeassistant/components/loopenergy/sensor.py
homeassistant/components/luci/device_tracker.py
@ -341,6 +346,7 @@ omit =
homeassistant/components/meteo_france/*
homeassistant/components/metoffice/sensor.py
homeassistant/components/metoffice/weather.py
homeassistant/components/microsoft/tts.py
homeassistant/components/miflora/sensor.py
homeassistant/components/mikrotik/device_tracker.py
homeassistant/components/mill/climate.py
@ -363,8 +369,8 @@ omit =
homeassistant/components/mystrom/binary_sensor.py
homeassistant/components/mystrom/light.py
homeassistant/components/mystrom/switch.py
homeassistant/components/n26/*
homeassistant/components/nad/media_player.py
homeassistant/components/nadtcp/media_player.py
homeassistant/components/nanoleaf/light.py
homeassistant/components/neato/*
homeassistant/components/nederlandse_spoorwegen/sensor.py
@ -373,7 +379,6 @@ omit =
homeassistant/components/netatmo/*
homeassistant/components/netatmo_public/sensor.py
homeassistant/components/netdata/sensor.py
homeassistant/components/netdata_public/sensor.py
homeassistant/components/netgear/device_tracker.py
homeassistant/components/netgear_lte/*
homeassistant/components/netio/switch.py
@ -394,6 +399,7 @@ omit =
homeassistant/components/nzbget/sensor.py
homeassistant/components/octoprint/*
homeassistant/components/oem/climate.py
homeassistant/components/oasa_telematics/sensor.py
homeassistant/components/ohmconnect/sensor.py
homeassistant/components/onewire/sensor.py
homeassistant/components/onkyo/media_player.py
@ -422,6 +428,7 @@ omit =
homeassistant/components/pencom/switch.py
homeassistant/components/philips_js/media_player.py
homeassistant/components/pi_hole/sensor.py
homeassistant/components/picotts/tts.py
homeassistant/components/piglow/light.py
homeassistant/components/pilight/*
homeassistant/components/ping/binary_sensor.py
@ -533,6 +540,7 @@ omit =
homeassistant/components/sochain/sensor.py
homeassistant/components/socialblade/sensor.py
homeassistant/components/solaredge/sensor.py
homeassistant/components/somfy_mylink/*
homeassistant/components/sonarr/sensor.py
homeassistant/components/songpal/media_player.py
homeassistant/components/sonos/*
@ -546,6 +554,7 @@ omit =
homeassistant/components/srp_energy/sensor.py
homeassistant/components/starlingbank/sensor.py
homeassistant/components/steam_online/sensor.py
homeassistant/components/stiebel_eltron/*
homeassistant/components/stride/notify.py
homeassistant/components/supervisord/sensor.py
homeassistant/components/swiss_hydrological_data/sensor.py
@ -573,7 +582,6 @@ omit =
homeassistant/components/tellduslive/*
homeassistant/components/tellstick/*
homeassistant/components/telnet/switch.py
homeassistant/components/telstra/notify.py
homeassistant/components/temper/sensor.py
homeassistant/components/tensorflow/image_processing.py
homeassistant/components/tesla/*
@ -605,10 +613,6 @@ omit =
homeassistant/components/trafikverket_weatherstation/sensor.py
homeassistant/components/transmission/*
homeassistant/components/travisci/sensor.py
homeassistant/components/tts/amazon_polly.py
homeassistant/components/tts/baidu.py
homeassistant/components/tts/microsoft.py
homeassistant/components/tts/picotts.py
homeassistant/components/tuya/*
homeassistant/components/twilio_call/notify.py
homeassistant/components/twilio_sms/notify.py
@ -650,6 +654,7 @@ omit =
homeassistant/components/wirelesstag/*
homeassistant/components/worldtidesinfo/sensor.py
homeassistant/components/worxlandroid/sensor.py
homeassistant/components/wunderlist/*
homeassistant/components/x10/light.py
homeassistant/components/xbox_live/sensor.py
homeassistant/components/xeoma/camera.py
@ -663,7 +668,7 @@ omit =
homeassistant/components/yale_smart_alarm/alarm_control_panel.py
homeassistant/components/yamaha/media_player.py
homeassistant/components/yamaha_musiccast/media_player.py
homeassistant/components/yeelight/light.py
homeassistant/components/yeelight/*
homeassistant/components/yeelightsunflower/light.py
homeassistant/components/yi/camera.py
homeassistant/components/zabbix/*
@ -688,6 +693,7 @@ omit =
homeassistant/components/zigbee/*
homeassistant/components/ziggo_mediabox_xl/media_player.py
homeassistant/components/zoneminder/*
homeassistant/components/supla/*
homeassistant/components/zwave/util.py
[report]

View File

@ -23,7 +23,8 @@ If user exposed functionality or configuration variables are added/changed:
- [ ] Documentation added/updated in [home-assistant.io](https://github.com/home-assistant/home-assistant.io)
If the code communicates with devices, web services, or third-party tools:
- [ ] New dependencies have been added to the `REQUIREMENTS` variable ([example][ex-requir]).
- [ ] [_The manifest file_][manifest-docs] has all fields filled out correctly ([example][ex-manifest]).
- [ ] New dependencies have been added to `requirements` in the manifest ([example][ex-requir]).
- [ ] New dependencies are only imported inside functions that use them ([example][ex-import]).
- [ ] New or updated dependencies have been added to `requirements_all.txt` by running `script/gen_requirements_all.py`.
- [ ] New files were added to `.coveragerc`.
@ -31,5 +32,7 @@ If the code communicates with devices, web services, or third-party tools:
If the code does not interact with devices:
- [ ] Tests have been added to verify that the new code works.
[ex-requir]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard/__init__.py#L14
[ex-manifest]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/mobile_app/manifest.json
[ex-requir]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/mobile_app/manifest.json#L5
[ex-import]: https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/keyboard/__init__.py#L23
[manifest-docs]: https://developers.home-assistant.io/docs/en/development_checklist.html#_the-manifest-file_

45
.github/main.workflow vendored
View File

@ -1,41 +1,14 @@
workflow "Python 3.7 - tox" {
resolves = ["Python 3.7 - tests"]
on = "push"
workflow "Mention CODEOWNERS of integrations when integration label is added to an issue" {
on = "issues"
resolves = "codeowners-mention"
}
action "Python 3.7 - tests" {
uses = "home-assistant/actions/py37-tox@master"
args = "-e py37"
workflow "Mention CODEOWNERS of integrations when integration label is added to an PRs" {
on = "pull_request"
resolves = "codeowners-mention"
}
workflow "Python 3.6 - tox" {
resolves = ["Python 3.6 - tests"]
on = "push"
}
action "Python 3.6 - tests" {
uses = "home-assistant/actions/py36-tox@master"
args = "-e py36"
}
workflow "Python 3.5 - tox" {
resolves = ["Pyton 3.5 - typing"]
on = "push"
}
action "Python 3.5 - tests" {
uses = "home-assistant/actions/py35-tox@master"
args = "-e py35"
}
action "Python 3.5 - lints" {
uses = "home-assistant/actions/py35-tox@master"
needs = ["Python 3.5 - tests"]
args = "-e lint"
}
action "Pyton 3.5 - typing" {
uses = "home-assistant/actions/py35-tox@master"
args = "-e typing"
needs = ["Python 3.5 - lints"]
action "codeowners-mention" {
uses = "home-assistant/codeowners-mention@master"
secrets = ["GITHUB_TOKEN"]
}

View File

@ -1,55 +0,0 @@
sudo: false
dist: xenial
addons:
apt:
sources:
- sourceline: "ppa:jonathonf/ffmpeg-4"
packages:
- libudev-dev
- libavformat-dev
- libavcodec-dev
- libavdevice-dev
- libavutil-dev
- libswscale-dev
- libswresample-dev
- libavfilter-dev
matrix:
fast_finish: true
include:
- python: "3.5.3"
env: TOXENV=lint
- python: "3.5.3"
env: TOXENV=pylint
- python: "3.5.3"
env: TOXENV=typing
- python: "3.5.3"
env: TOXENV=cov
after_success: coveralls
- python: "3.6"
env: TOXENV=py36
- python: "3.7"
env: TOXENV=py37
- python: "3.8-dev"
env: TOXENV=py38
if: branch = dev AND type = push
allow_failures:
- python: "3.8-dev"
env: TOXENV=py38
cache:
directories:
- $HOME/.cache/pip
install: pip install -U tox coveralls
language: python
script: travis_wait 40 tox --develop
services:
- docker
before_deploy:
- docker pull lokalise/lokalise-cli@sha256:2198814ebddfda56ee041a4b427521757dd57f75415ea9693696a64c550cef21
deploy:
skip_cleanup: true
provider: script
script: script/travis_deploy
on:
branch: dev
condition: $TOXENV = lint

View File

@ -1,3 +1,4 @@
# This file is generated by script/manifest/codeowners.py
# People marked here will be automatically requested for a review
# when the code that they own is touched.
# https://github.com/blog/2392-introducing-code-owners
@ -7,285 +8,255 @@ setup.py @home-assistant/core
homeassistant/*.py @home-assistant/core
homeassistant/helpers/* @home-assistant/core
homeassistant/util/* @home-assistant/core
homeassistant/components/api/* @home-assistant/core
homeassistant/components/auth/* @home-assistant/core
homeassistant/components/automation/* @home-assistant/core
homeassistant/components/cloud/* @home-assistant/core
homeassistant/components/config/* @home-assistant/core
homeassistant/components/configurator/* @home-assistant/core
homeassistant/components/conversation/* @home-assistant/core
homeassistant/components/frontend/* @home-assistant/core
homeassistant/components/group/* @home-assistant/core
homeassistant/components/history/* @home-assistant/core
homeassistant/components/http/* @home-assistant/core
homeassistant/components/input_*/* @home-assistant/core
homeassistant/components/introduction/* @home-assistant/core
homeassistant/components/logger/* @home-assistant/core
homeassistant/components/lovelace/* @home-assistant/core
homeassistant/components/mqtt/* @home-assistant/core
homeassistant/components/panel_custom/* @home-assistant/core
homeassistant/components/panel_iframe/* @home-assistant/core
homeassistant/components/onboarding/* @home-assistant/core
homeassistant/components/persistent_notification/* @home-assistant/core
homeassistant/components/scene/__init__.py @home-assistant/core
homeassistant/components/scene/homeassistant.py @home-assistant/core
homeassistant/components/script/* @home-assistant/core
homeassistant/components/shell_command/* @home-assistant/core
homeassistant/components/sun/* @home-assistant/core
homeassistant/components/updater/* @home-assistant/core
homeassistant/components/weblink/* @home-assistant/core
homeassistant/components/websocket_api/* @home-assistant/core
homeassistant/components/zone/* @home-assistant/core
# Home Assistant Developer Teams
# Virtualization
Dockerfile @home-assistant/docker
virtualization/Docker/* @home-assistant/docker
homeassistant/components/zwave/* @home-assistant/z-wave
homeassistant/components/*/zwave.py @home-assistant/z-wave
# Other code
homeassistant/scripts/check_config.py @kellerza
homeassistant/components/hassio/* @home-assistant/hassio
# Individual platforms
homeassistant/components/notify/aws_lambda.py @robbiet480
homeassistant/components/notify/aws_sns.py @robbiet480
homeassistant/components/notify/aws_sqs.py @robbiet480
homeassistant/components/notify/file.py @fabaff
homeassistant/components/notify/flock.py @fabaff
homeassistant/components/notify/gntp.py @robbiet480
homeassistant/components/notify/html5.py @robbiet480
homeassistant/components/notify/mastodon.py @fabaff
homeassistant/components/notify/smtp.py @fabaff
homeassistant/components/notify/syslog.py @fabaff
homeassistant/components/notify/twilio_call.py @robbiet480
homeassistant/components/notify/twilio_sms.py @robbiet480
homeassistant/components/notify/xmpp.py @fabaff
homeassistant/components/notify/yessssms.py @flowolf
homeassistant/components/tts/amazon_polly.py @robbiet480
# A
homeassistant/components/airvisual/sensor.py @bachya
homeassistant/components/alarm_control_panel/manual_mqtt.py @colinodell
homeassistant/components/alpha_vantage/sensor.py @fabaff
# Integrations
homeassistant/components/airvisual/* @bachya
homeassistant/components/alarm_control_panel/* @colinodell
homeassistant/components/alpha_vantage/* @fabaff
homeassistant/components/amazon_polly/* @robbiet480
homeassistant/components/ambient_station/* @bachya
homeassistant/components/api/* @home-assistant/core
homeassistant/components/arduino/* @fabaff
homeassistant/components/arest/* @fabaff
homeassistant/components/asuswrt/device_tracker.py @kennedyshead
homeassistant/components/automatic/device_tracker.py @armills
homeassistant/components/asuswrt/* @kennedyshead
homeassistant/components/auth/* @home-assistant/core
homeassistant/components/automatic/* @armills
homeassistant/components/automation/* @home-assistant/core
homeassistant/components/aws/* @awarecan @robbiet480
homeassistant/components/axis/* @kane610
# B
homeassistant/components/bitcoin/sensor.py @fabaff
homeassistant/components/bitcoin/* @fabaff
homeassistant/components/blink/* @fronzbot
homeassistant/components/bmw_connected_drive/* @ChristianKuehnel
homeassistant/components/braviatv/media_player.py @robbiet480
homeassistant/components/braviatv/* @robbiet480
homeassistant/components/broadlink/* @danielhiversen
homeassistant/components/brunt/cover.py @eavanvalkenburg
homeassistant/components/bt_smarthub/device_tracker.py @jxwolstenholme
# C
homeassistant/components/brunt/* @eavanvalkenburg
homeassistant/components/bt_smarthub/* @jxwolstenholme
homeassistant/components/cisco_ios/* @fbradyirl
homeassistant/components/cisco_mobility_express/* @fbradyirl
homeassistant/components/cisco_webex_teams/* @fbradyirl
homeassistant/components/ciscospark/* @fbradyirl
homeassistant/components/cloud/* @home-assistant/core
homeassistant/components/cloudflare/* @ludeeus
homeassistant/components/coolmaster/climate.py @OnFreund
homeassistant/components/config/* @home-assistant/core
homeassistant/components/configurator/* @home-assistant/core
homeassistant/components/conversation/* @home-assistant/core
homeassistant/components/coolmaster/* @OnFreund
homeassistant/components/counter/* @fabaff
homeassistant/components/cover/group.py @cdce8p
homeassistant/components/cpuspeed/sensor.py @fabaff
homeassistant/components/cups/sensor.py @fabaff
# D
homeassistant/components/cover/* @home-assistant/core
homeassistant/components/cpuspeed/* @fabaff
homeassistant/components/cups/* @fabaff
homeassistant/components/daikin/* @fredrike @rofrantz
homeassistant/components/darksky/* @fabaff
homeassistant/components/discogs/sensor.py @thibmaek
homeassistant/components/deconz/* @kane610
homeassistant/components/demo/weather.py @fabaff
homeassistant/components/demo/* @home-assistant/core
homeassistant/components/digital_ocean/* @fabaff
homeassistant/components/discogs/* @thibmaek
homeassistant/components/doorbird/* @oblogic7
homeassistant/components/dweet/* @fabaff
# E
homeassistant/components/ecovacs/* @OverloadUT
homeassistant/components/edp_redy/* @abmantis
homeassistant/components/eight_sleep/* @mezz64
homeassistant/components/egardia/* @jeroenterheerdt
homeassistant/components/emby/media_player.py @mezz64
homeassistant/components/ephember/climate.py @ttroy50
homeassistant/components/eq3btsmart/climate.py @rytilahti
homeassistant/components/eight_sleep/* @mezz64
homeassistant/components/emby/* @mezz64
homeassistant/components/enigma2/* @fbradyirl
homeassistant/components/ephember/* @ttroy50
homeassistant/components/epsonworkforce/* @ThaStealth
homeassistant/components/eq3btsmart/* @rytilahti
homeassistant/components/esphome/* @OttoWinter
# F
homeassistant/components/file/sensor.py @fabaff
homeassistant/components/filter/sensor.py @dgomes
homeassistant/components/fitbit/sensor.py @robbiet480
homeassistant/components/fixer/sensor.py @fabaff
homeassistant/components/flunearyou/sensor.py @bachya
homeassistant/components/file/* @fabaff
homeassistant/components/filter/* @dgomes
homeassistant/components/fitbit/* @robbiet480
homeassistant/components/fixer/* @fabaff
homeassistant/components/flock/* @fabaff
homeassistant/components/flunearyou/* @bachya
homeassistant/components/foursquare/* @robbiet480
homeassistant/components/freebox/* @snoof85
# G
homeassistant/components/gearbest/sensor.py @HerrHofrat
homeassistant/components/gitter/sensor.py @fabaff
homeassistant/components/glances/sensor.py @fabaff
homeassistant/components/google_travel_time/sensor.py @robbiet480
homeassistant/components/frontend/* @home-assistant/core
homeassistant/components/gearbest/* @HerrHofrat
homeassistant/components/gitter/* @fabaff
homeassistant/components/glances/* @fabaff
homeassistant/components/gntp/* @robbiet480
homeassistant/components/google_translate/* @awarecan
homeassistant/components/google_travel_time/* @robbiet480
homeassistant/components/googlehome/* @ludeeus
homeassistant/components/gpsd/sensor.py @fabaff
homeassistant/components/gtfs/sensor.py @robbiet480
# H
homeassistant/components/gpsd/* @fabaff
homeassistant/components/group/* @home-assistant/core
homeassistant/components/gtfs/* @robbiet480
homeassistant/components/harmony/* @ehendrix23
homeassistant/components/hikvision/binary_sensor.py @mezz64
homeassistant/components/hassio/* @home-assistant/hass-io
homeassistant/components/heos/* @andrewsayre
homeassistant/components/hikvision/* @mezz64
homeassistant/components/hikvisioncam/* @fbradyirl
homeassistant/components/history/* @home-assistant/core
homeassistant/components/history_graph/* @andrey-git
homeassistant/components/hive/* @Rendili @KJonline
homeassistant/components/homeassistant/* @home-assistant/core
homeassistant/components/homekit/* @cdce8p
homeassistant/components/homematic/* @pvizeli @danielperna84
homeassistant/components/html5/* @robbiet480
homeassistant/components/http/* @home-assistant/core
homeassistant/components/huawei_lte/* @scop
homeassistant/components/huawei_router/device_tracker.py @abmantis
# I
homeassistant/components/huawei_router/* @abmantis
homeassistant/components/hue/* @balloob
homeassistant/components/ign_sismologia/* @exxamalte
homeassistant/components/influxdb/* @fabaff
homeassistant/components/integration/sensor.py @dgomes
homeassistant/components/input_boolean/* @home-assistant/core
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/integration/* @dgomes
homeassistant/components/ios/* @robbiet480
homeassistant/components/ipma/* @dgomes
homeassistant/components/irish_rail_transport/sensor.py @ttroy50
# J
homeassistant/components/jewish_calendar/sensor.py @tsvi
# K
homeassistant/components/irish_rail_transport/* @ttroy50
homeassistant/components/jewish_calendar/* @tsvi
homeassistant/components/knx/* @Julius2342
homeassistant/components/kodi/media_player.py @armills
homeassistant/components/kodi/* @armills
homeassistant/components/konnected/* @heythisisnate
# L
homeassistant/components/lametric/notify.py @robbiet480
homeassistant/components/launch_library/sensor.py @ludeeus
homeassistant/components/lametric/* @robbiet480
homeassistant/components/launch_library/* @ludeeus
homeassistant/components/lifx/* @amelchio
homeassistant/components/lifx_cloud/scene.py @amelchio
homeassistant/components/lifx_legacy/light.py @amelchio
homeassistant/components/linux_battery/sensor.py @fabaff
homeassistant/components/liveboxplaytv/media_player.py @pschmitt
homeassistant/components/lifx_cloud/* @amelchio
homeassistant/components/lifx_legacy/* @amelchio
homeassistant/components/linux_battery/* @fabaff
homeassistant/components/liveboxplaytv/* @pschmitt
homeassistant/components/logger/* @home-assistant/core
homeassistant/components/logi_circle/* @evanjd
homeassistant/components/lovelace/* @home-assistant/core
homeassistant/components/luci/* @fbradyirl
homeassistant/components/luftdaten/* @fabaff
# M
homeassistant/components/mastodon/* @fabaff
homeassistant/components/matrix/* @tinloaf
homeassistant/components/mediaroom/media_player.py @dgomes
homeassistant/components/mediaroom/* @dgomes
homeassistant/components/melissa/* @kennedyshead
homeassistant/components/met/weather.py @danielhiversen
homeassistant/components/miflora/sensor.py @danielhiversen @ChristianKuehnel
homeassistant/components/mill/climate.py @danielhiversen
homeassistant/components/min_max/sensor.py @fabaff
homeassistant/components/met/* @danielhiversen
homeassistant/components/miflora/* @danielhiversen @ChristianKuehnel
homeassistant/components/mill/* @danielhiversen
homeassistant/components/min_max/* @fabaff
homeassistant/components/mobile_app/* @robbiet480
homeassistant/components/monoprice/media_player.py @etsinko
homeassistant/components/moon/sensor.py @fabaff
homeassistant/components/mpd/media_player.py @fabaff
homeassistant/components/monoprice/* @etsinko
homeassistant/components/moon/* @fabaff
homeassistant/components/mpd/* @fabaff
homeassistant/components/mqtt/* @home-assistant/core
homeassistant/components/mystrom/* @fabaff
# N
homeassistant/components/nello/lock.py @pschmitt
homeassistant/components/nello/* @pschmitt
homeassistant/components/ness_alarm/* @nickw444
homeassistant/components/netdata/sensor.py @fabaff
homeassistant/components/nest/* @awarecan
homeassistant/components/netdata/* @fabaff
homeassistant/components/nissan_leaf/* @filcole
homeassistant/components/nmbs/sensor.py @thibmaek
homeassistant/components/nmbs/* @thibmaek
homeassistant/components/no_ip/* @fabaff
homeassistant/components/nuki/lock.py @pschmitt
homeassistant/components/nsw_fuel_station/sensor.py @nickw444
# O
homeassistant/components/ohmconnect/sensor.py @robbiet480
homeassistant/components/notify/* @flowolf
homeassistant/components/nsw_fuel_station/* @nickw444
homeassistant/components/nuki/* @pschmitt
homeassistant/components/ohmconnect/* @robbiet480
homeassistant/components/onboarding/* @home-assistant/core
homeassistant/components/openuv/* @bachya
homeassistant/components/openweathermap/weather.py @fabaff
homeassistant/components/openweathermap/* @fabaff
homeassistant/components/owlet/* @oblogic7
# P
homeassistant/components/pi_hole/sensor.py @fabaff
homeassistant/components/panel_custom/* @home-assistant/core
homeassistant/components/panel_iframe/* @home-assistant/core
homeassistant/components/persistent_notification/* @home-assistant/core
homeassistant/components/pi_hole/* @fabaff
homeassistant/components/plant/* @ChristianKuehnel
homeassistant/components/point/* @fredrike
homeassistant/components/pollen/sensor.py @bachya
homeassistant/components/push/camera.py @dgomes
homeassistant/components/pvoutput/sensor.py @fabaff
# Q
homeassistant/components/qnap/sensor.py @colinodell
homeassistant/components/quantum_gateway/device_tracker.py @cisasteelersfan
homeassistant/components/pollen/* @bachya
homeassistant/components/push/* @dgomes
homeassistant/components/pvoutput/* @fabaff
homeassistant/components/qnap/* @colinodell
homeassistant/components/quantum_gateway/* @cisasteelersfan
homeassistant/components/qwikswitch/* @kellerza
# R
homeassistant/components/raincloud/* @vanstinator
homeassistant/components/rainmachine/* @bachya
homeassistant/components/random/* @fabaff
homeassistant/components/rfxtrx/* @danielhiversen
homeassistant/components/rmvtransport/* @cgtobi
homeassistant/components/roomba/vacuum.py @pschmitt
homeassistant/components/ruter/sensor.py @ludeeus
# S
homeassistant/components/scrape/sensor.py @fabaff
homeassistant/components/sensibo/climate.py @andrey-git
homeassistant/components/serial/sensor.py @fabaff
homeassistant/components/seventeentrack/sensor.py @bachya
homeassistant/components/roomba/* @pschmitt
homeassistant/components/ruter/* @ludeeus
homeassistant/components/scene/* @home-assistant/core
homeassistant/components/scrape/* @fabaff
homeassistant/components/script/* @home-assistant/core
homeassistant/components/sensibo/* @andrey-git
homeassistant/components/serial/* @fabaff
homeassistant/components/seventeentrack/* @bachya
homeassistant/components/shell_command/* @home-assistant/core
homeassistant/components/shiftr/* @fabaff
homeassistant/components/shodan/sensor.py @fabaff
homeassistant/components/shodan/* @fabaff
homeassistant/components/simplisafe/* @bachya
homeassistant/components/sma/sensor.py @kellerza
homeassistant/components/sma/* @kellerza
homeassistant/components/smartthings/* @andrewsayre
homeassistant/components/smtp/* @fabaff
homeassistant/components/sonos/* @amelchio
homeassistant/components/spaceapi/* @fabaff
homeassistant/components/spider/* @peternijssen
homeassistant/components/sql/sensor.py @dgomes
homeassistant/components/statistics/sensor.py @fabaff
homeassistant/components/swiss_*/* @fabaff
homeassistant/components/switchbot/switch.py @danielhiversen
homeassistant/components/switchmate/switch.py @danielhiversen
homeassistant/components/synology_srm/device_tracker.py @aerialls
homeassistant/components/sytadin/sensor.py @gautric
# T
homeassistant/components/sql/* @dgomes
homeassistant/components/statistics/* @fabaff
homeassistant/components/stiebel_eltron/* @fucm
homeassistant/components/sun/* @home-assistant/core
homeassistant/components/supla/* @mwegrzynek
homeassistant/components/swiss_hydrological_data/* @fabaff
homeassistant/components/swiss_public_transport/* @fabaff
homeassistant/components/switchbot/* @danielhiversen
homeassistant/components/switchmate/* @danielhiversen
homeassistant/components/synology_srm/* @aerialls
homeassistant/components/syslog/* @fabaff
homeassistant/components/sytadin/* @gautric
homeassistant/components/tahoma/* @philklei
homeassistant/components/tautulli/sensor.py @ludeeus
homeassistant/components/tautulli/* @ludeeus
homeassistant/components/tellduslive/* @fredrike
homeassistant/components/template/cover.py @PhracturedBlue
homeassistant/components/template/* @PhracturedBlue
homeassistant/components/tesla/* @zabuldon
homeassistant/components/tfiac/* @fredrike @mellado
homeassistant/components/thethingsnetwork/* @fabaff
homeassistant/components/threshold/binary_sensor.py @fabaff
homeassistant/components/threshold/* @fabaff
homeassistant/components/tibber/* @danielhiversen
homeassistant/components/tile/device_tracker.py @bachya
homeassistant/components/time_date/sensor.py @fabaff
homeassistant/components/tile/* @bachya
homeassistant/components/time_date/* @fabaff
homeassistant/components/toon/* @frenck
homeassistant/components/tplink/* @rytilahti
homeassistant/components/traccar/device_tracker.py @ludeeus
homeassistant/components/traccar/* @ludeeus
homeassistant/components/tradfri/* @ggravlingen
# U
homeassistant/components/uber/sensor.py @robbiet480
homeassistant/components/tts/* @robbiet480
homeassistant/components/twilio_call/* @robbiet480
homeassistant/components/twilio_sms/* @robbiet480
homeassistant/components/uber/* @robbiet480
homeassistant/components/unifi/* @kane610
homeassistant/components/upcloud/* @scop
homeassistant/components/updater/* @home-assistant/core
homeassistant/components/upnp/* @robbiet480
homeassistant/components/uptimerobot/binary_sensor.py @ludeeus
homeassistant/components/uptimerobot/* @ludeeus
homeassistant/components/utility_meter/* @dgomes
# V
homeassistant/components/velux/* @Julius2342
homeassistant/components/version/sensor.py @fabaff
# W
homeassistant/components/waqi/sensor.py @andrey-git
homeassistant/components/weather/__init__.py @fabaff
homeassistant/components/version/* @fabaff
homeassistant/components/waqi/* @andrey-git
homeassistant/components/weather/* @fabaff
homeassistant/components/weblink/* @home-assistant/core
homeassistant/components/websocket_api/* @home-assistant/core
homeassistant/components/wemo/* @sqldiablo
homeassistant/components/worldclock/sensor.py @fabaff
# X
homeassistant/components/xfinity/device_tracker.py @cisasteelersfan
homeassistant/components/worldclock/* @fabaff
homeassistant/components/xfinity/* @cisasteelersfan
homeassistant/components/xiaomi_aqara/* @danielhiversen @syssi
homeassistant/components/xiaomi_miio/* @rytilahti @syssi
homeassistant/components/xiaomi_tv/media_player.py @fattdev
# Y
homeassistant/components/xiaomi_tv/* @fattdev
homeassistant/components/xmpp/* @fabaff
homeassistant/components/yamaha_musiccast/* @jalmeroth
homeassistant/components/yeelight/* @rytilahti @zewelor
homeassistant/components/yeelightsunflower/light.py @lindsaymarkward
homeassistant/components/yi/camera.py @bachya
# Z
homeassistant/components/yeelightsunflower/* @lindsaymarkward
homeassistant/components/yessssms/* @flowolf
homeassistant/components/yi/* @bachya
homeassistant/components/zeroconf/* @robbiet480
homeassistant/components/zha/* @dmulcahey @adminiuga
homeassistant/components/zone/* @home-assistant/core
homeassistant/components/zoneminder/* @rohankapoorcom
homeassistant/components/zwave/* @home-assistant/z-wave
# Other code
homeassistant/scripts/check_config.py @kellerza
# Individual files
homeassistant/components/group/cover @cdce8p
homeassistant/components/demo/weather @fabaff

View File

@ -27,7 +27,7 @@ COPY requirements_all.txt requirements_all.txt
# Uninstall enum34 because some dependencies install it but breaks Python 3.4+.
# See PR #8103 for more info.
RUN pip3 install --no-cache-dir -r requirements_all.txt && \
pip3 install --no-cache-dir mysqlclient psycopg2 uvloop==0.11.3 cchardet cython tensorflow
pip3 install --no-cache-dir mysqlclient psycopg2 uvloop==0.12.2 cchardet cython tensorflow
# Copy source
COPY . .

View File

@ -11,9 +11,6 @@ from typing import Any, Optional, Dict, Set
import voluptuous as vol
from homeassistant import core, config as conf_util, config_entries, loader
from homeassistant.components import (
persistent_notification, homeassistant as core_component
)
from homeassistant.const import EVENT_HOMEASSISTANT_CLOSE
from homeassistant.setup import async_setup_component
from homeassistant.util.logging import AsyncHandler
@ -29,50 +26,16 @@ ERROR_LOG_FILENAME = 'home-assistant.log'
# hass.data key for logging information.
DATA_LOGGING = 'logging'
LOGGING_COMPONENT = {'logger', 'system_log'}
FIRST_INIT_COMPONENT = {
CORE_INTEGRATIONS = ('homeassistant', 'persistent_notification')
LOGGING_INTEGRATIONS = {'logger', 'system_log'}
STAGE_1_INTEGRATIONS = {
# To record data
'recorder',
'mqtt',
# To make sure we forward data to other instances
'mqtt_eventstream',
'introduction',
'frontend',
'history',
}
def from_config_dict(config: Dict[str, Any],
hass: Optional[core.HomeAssistant] = None,
config_dir: Optional[str] = None,
enable_log: bool = True,
verbose: bool = False,
skip_pip: bool = False,
log_rotate_days: Any = None,
log_file: Any = None,
log_no_color: bool = False) \
-> Optional[core.HomeAssistant]:
"""Try to configure Home Assistant from a configuration dictionary.
Dynamically loads required components and its dependencies.
"""
if hass is None:
hass = core.HomeAssistant()
if config_dir is not None:
config_dir = os.path.abspath(config_dir)
hass.config.config_dir = config_dir
if not is_virtual_env():
hass.loop.run_until_complete(
async_mount_local_lib_path(config_dir))
# run task
hass = hass.loop.run_until_complete(
async_from_config_dict(
config, hass, config_dir, enable_log, verbose, skip_pip,
log_rotate_days, log_file, log_no_color)
)
return hass
async def async_from_config_dict(config: Dict[str, Any],
hass: core.HomeAssistant,
config_dir: Optional[str] = None,
@ -115,70 +78,17 @@ async def async_from_config_dict(config: Dict[str, Any],
"Further initialization aborted")
return None
await hass.async_add_executor_job(
conf_util.process_ha_config_upgrade, hass)
# Make a copy because we are mutating it.
config = OrderedDict(config)
# Merge packages
conf_util.merge_packages_config(
await conf_util.merge_packages_config(
hass, config, core_config.get(conf_util.CONF_PACKAGES, {}))
hass.config_entries = config_entries.ConfigEntries(hass, config)
await hass.config_entries.async_initialize()
components = _get_components(hass, config)
# Resolve all dependencies of all components.
for component in list(components):
try:
components.update(loader.component_dependencies(hass, component))
except loader.LoaderError:
# Ignore it, or we'll break startup
# It will be properly handled during setup.
pass
# setup components
res = await core_component.async_setup(hass, config)
if not res:
_LOGGER.error("Home Assistant core failed to initialize. "
"Further initialization aborted")
return hass
await persistent_notification.async_setup(hass, config)
_LOGGER.info("Home Assistant core initialized")
# stage 0, load logging components
for component in components:
if component in LOGGING_COMPONENT:
hass.async_create_task(
async_setup_component(hass, component, config))
await hass.async_block_till_done()
# Kick off loading the registries. They don't need to be awaited.
asyncio.gather(
hass.helpers.device_registry.async_get_registry(),
hass.helpers.entity_registry.async_get_registry(),
hass.helpers.area_registry.async_get_registry())
# stage 1
for component in components:
if component in FIRST_INIT_COMPONENT:
hass.async_create_task(
async_setup_component(hass, component, config))
await hass.async_block_till_done()
# stage 2
for component in components:
if component in FIRST_INIT_COMPONENT or component in LOGGING_COMPONENT:
continue
hass.async_create_task(async_setup_component(hass, component, config))
await hass.async_block_till_done()
await _async_set_up_integrations(hass, config)
stop = time()
_LOGGER.info("Home Assistant initialized in %.2fs", stop-start)
@ -231,32 +141,6 @@ async def async_from_config_dict(config: Dict[str, Any],
return hass
def from_config_file(config_path: str,
hass: Optional[core.HomeAssistant] = None,
verbose: bool = False,
skip_pip: bool = True,
log_rotate_days: Any = None,
log_file: Any = None,
log_no_color: bool = False)\
-> Optional[core.HomeAssistant]:
"""Read the configuration file and try to start all the functionality.
Will add functionality to 'hass' parameter if given,
instantiates a new Home Assistant object if 'hass' is not given.
"""
if hass is None:
hass = core.HomeAssistant()
# run task
hass = hass.loop.run_until_complete(
async_from_config_file(
config_path, hass, verbose, skip_pip,
log_rotate_days, log_file, log_no_color)
)
return hass
async def async_from_config_file(config_path: str,
hass: core.HomeAssistant,
verbose: bool = False,
@ -280,6 +164,9 @@ async def async_from_config_file(config_path: str,
async_enable_logging(hass, verbose, log_rotate_days, log_file,
log_no_color)
await hass.async_add_executor_job(
conf_util.process_ha_config_upgrade, hass)
try:
config_dict = await hass.async_add_executor_job(
conf_util.load_yaml_config_file, config_path)
@ -398,18 +285,127 @@ async def async_mount_local_lib_path(config_dir: str) -> str:
@core.callback
def _get_components(hass: core.HomeAssistant,
config: Dict[str, Any]) -> Set[str]:
"""Get components to set up."""
def _get_domains(hass: core.HomeAssistant, config: Dict[str, Any]) -> Set[str]:
"""Get domains of components to set up."""
# Filter out the repeating and common config section [homeassistant]
components = set(key.split(' ')[0] for key in config.keys()
if key != core.DOMAIN)
domains = set(key.split(' ')[0] for key in config.keys()
if key != core.DOMAIN)
# Add config entry domains
components.update(hass.config_entries.async_domains()) # type: ignore
domains.update(hass.config_entries.async_domains()) # type: ignore
# Make sure the Hass.io component is loaded
if 'HASSIO' in os.environ:
components.add('hassio')
domains.add('hassio')
return components
return domains
async def _async_set_up_integrations(
hass: core.HomeAssistant, config: Dict[str, Any]) -> None:
"""Set up all the integrations."""
domains = _get_domains(hass, config)
# Resolve all dependencies of all components so we can find the logging
# and integrations that need faster initialization.
resolved_domains_task = asyncio.gather(*[
loader.async_component_dependencies(hass, domain)
for domain in domains
], return_exceptions=True)
# Set up core.
_LOGGER.debug("Setting up %s", CORE_INTEGRATIONS)
if not all(await asyncio.gather(*[
async_setup_component(hass, domain, config)
for domain in CORE_INTEGRATIONS
])):
_LOGGER.error("Home Assistant core failed to initialize. "
"Further initialization aborted")
return
_LOGGER.debug("Home Assistant core initialized")
# Finish resolving domains
for dep_domains in await resolved_domains_task:
# Result is either a set or an exception. We ignore exceptions
# It will be properly handled during setup of the domain.
if isinstance(dep_domains, set):
domains.update(dep_domains)
# setup components
logging_domains = domains & LOGGING_INTEGRATIONS
stage_1_domains = domains & STAGE_1_INTEGRATIONS
stage_2_domains = domains - logging_domains - stage_1_domains
if logging_domains:
_LOGGER.debug("Setting up %s", logging_domains)
await asyncio.gather(*[
async_setup_component(hass, domain, config)
for domain in logging_domains
])
# Kick off loading the registries. They don't need to be awaited.
asyncio.gather(
hass.helpers.device_registry.async_get_registry(),
hass.helpers.entity_registry.async_get_registry(),
hass.helpers.area_registry.async_get_registry())
if stage_1_domains:
await asyncio.gather(*[
async_setup_component(hass, domain, config)
for domain in logging_domains
])
# Load all integrations
after_dependencies = {} # type: Dict[str, Set[str]]
for int_or_exc in await asyncio.gather(*[
loader.async_get_integration(hass, domain)
for domain in stage_2_domains
], return_exceptions=True):
# Exceptions are handled in async_setup_component.
if (isinstance(int_or_exc, loader.Integration) and
int_or_exc.after_dependencies):
after_dependencies[int_or_exc.domain] = set(
int_or_exc.after_dependencies
)
last_load = None
while stage_2_domains:
domains_to_load = set()
for domain in stage_2_domains:
after_deps = after_dependencies.get(domain)
# Load if integration has no after_dependencies or they are
# all loaded
if (not after_deps or
not after_deps-hass.config.components):
domains_to_load.add(domain)
if not domains_to_load or domains_to_load == last_load:
break
_LOGGER.debug("Setting up %s", domains_to_load)
await asyncio.gather(*[
async_setup_component(hass, domain, config)
for domain in domains_to_load
])
last_load = domains_to_load
stage_2_domains -= domains_to_load
# These are stage 2 domains that never have their after_dependencies
# satisfied.
if stage_2_domains:
_LOGGER.debug("Final set up: %s", stage_2_domains)
await asyncio.gather(*[
async_setup_component(hass, domain, config)
for domain in stage_2_domains
])
# Wrap up startup
await hass.async_block_till_done()

View File

@ -13,8 +13,6 @@ from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import discovery
from homeassistant.helpers.entity import Entity
REQUIREMENTS = ['abodepy==0.15.0']
_LOGGER = logging.getLogger(__name__)
ATTRIBUTION = "Data provided by goabode.com"

View File

@ -8,8 +8,6 @@ from homeassistant.const import (
from . import ATTRIBUTION, DOMAIN as ABODE_DOMAIN, AbodeDevice
DEPENDENCIES = ['abode']
_LOGGER = logging.getLogger(__name__)
ICON = 'mdi:security'

View File

@ -7,8 +7,6 @@ from . import DOMAIN as ABODE_DOMAIN, AbodeAutomation, AbodeDevice
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['abode']
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up a sensor for an Abode device."""

View File

@ -9,8 +9,6 @@ from homeassistant.util import Throttle
from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
DEPENDENCIES = ['abode']
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=90)
_LOGGER = logging.getLogger(__name__)

View File

@ -5,8 +5,6 @@ from homeassistant.components.cover import CoverDevice
from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
DEPENDENCIES = ['abode']
_LOGGER = logging.getLogger(__name__)

View File

@ -10,8 +10,6 @@ from homeassistant.util.color import (
from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
DEPENDENCIES = ['abode']
_LOGGER = logging.getLogger(__name__)

View File

@ -5,8 +5,6 @@ from homeassistant.components.lock import LockDevice
from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
DEPENDENCIES = ['abode']
_LOGGER = logging.getLogger(__name__)

View File

@ -0,0 +1,10 @@
{
"domain": "abode",
"name": "Abode",
"documentation": "https://www.home-assistant.io/components/abode",
"requirements": [
"abodepy==0.15.0"
],
"dependencies": [],
"codeowners": []
}

View File

@ -8,8 +8,6 @@ from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['abode']
# Sensor types: Name, icon
SENSOR_TYPES = {
'temp': ['Temperature', DEVICE_CLASS_TEMPERATURE],

View File

@ -7,8 +7,6 @@ from . import DOMAIN as ABODE_DOMAIN, AbodeAutomation, AbodeDevice
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['abode']
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up Abode switch devices."""

View File

@ -0,0 +1,10 @@
{
"domain": "acer_projector",
"name": "Acer projector",
"documentation": "https://www.home-assistant.io/components/acer_projector",
"requirements": [
"pyserial==3.1.1"
],
"dependencies": [],
"codeowners": []
}

View File

@ -1,9 +1,4 @@
"""
Use serial protocol of Acer projector to obtain state of the projector.
For more details about this component, please refer to the documentation
at https://home-assistant.io/components/switch.acer_projector/
"""
"""Use serial protocol of Acer projector to obtain state of the projector."""
import logging
import re
@ -14,8 +9,6 @@ from homeassistant.const import (
STATE_ON, STATE_OFF, STATE_UNKNOWN, CONF_NAME, CONF_FILENAME)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['pyserial==3.1.1']
_LOGGER = logging.getLogger(__name__)
CONF_TIMEOUT = 'timeout'

View File

@ -1,9 +1,4 @@
"""
Support for Actiontec MI424WR (Verizon FIOS) routers.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/device_tracker.actiontec/
"""
"""Support for Actiontec MI424WR (Verizon FIOS) routers."""
import logging
import re
import telnetlib

View File

@ -0,0 +1,8 @@
{
"domain": "actiontec",
"name": "Actiontec",
"documentation": "https://www.home-assistant.io/components/actiontec",
"requirements": [],
"dependencies": [],
"codeowners": []
}

View File

@ -4,14 +4,15 @@ import struct
import logging
import ctypes
from collections import namedtuple
import asyncio
import async_timeout
import voluptuous as vol
from homeassistant.const import (
CONF_DEVICE, CONF_IP_ADDRESS, CONF_PORT, EVENT_HOMEASSISTANT_STOP)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['pyads==3.0.7']
from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__)
@ -31,6 +32,9 @@ CONF_ADS_VALUE = 'value'
CONF_ADS_VAR = 'adsvar'
CONF_ADS_VAR_BRIGHTNESS = 'adsvar_brightness'
STATE_KEY_STATE = 'state'
STATE_KEY_BRIGHTNESS = 'brightness'
DOMAIN = 'ads'
SERVICE_WRITE_DATA_BY_NAME = 'write_data_by_name'
@ -154,28 +158,41 @@ class AdsHub:
def write_by_name(self, name, value, plc_datatype):
"""Write a value to the device."""
import pyads
with self._lock:
return self._client.write_by_name(name, value, plc_datatype)
try:
return self._client.write_by_name(name, value, plc_datatype)
except pyads.ADSError as err:
_LOGGER.error("Error writing %s: %s", name, err)
def read_by_name(self, name, plc_datatype):
"""Read a value from the device."""
import pyads
with self._lock:
return self._client.read_by_name(name, plc_datatype)
try:
return self._client.read_by_name(name, plc_datatype)
except pyads.ADSError as err:
_LOGGER.error("Error reading %s: %s", name, err)
def add_device_notification(self, name, plc_datatype, callback):
"""Add a notification to the ADS devices."""
from pyads import NotificationAttrib
attr = NotificationAttrib(ctypes.sizeof(plc_datatype))
import pyads
attr = pyads.NotificationAttrib(ctypes.sizeof(plc_datatype))
with self._lock:
hnotify, huser = self._client.add_device_notification(
name, attr, self._device_notification_callback)
hnotify = int(hnotify)
self._notification_items[hnotify] = NotificationItem(
hnotify, huser, name, plc_datatype, callback)
try:
hnotify, huser = self._client.add_device_notification(
name, attr, self._device_notification_callback)
except pyads.ADSError as err:
_LOGGER.error("Error subscribing to %s: %s", name, err)
else:
hnotify = int(hnotify)
self._notification_items[hnotify] = NotificationItem(
hnotify, huser, name, plc_datatype, callback)
_LOGGER.debug(
"Added device notification %d for variable %s", hnotify, name)
_LOGGER.debug(
"Added device notification %d for variable %s",
hnotify, name)
def _device_notification_callback(self, notification, name):
"""Handle device notifications."""
@ -210,3 +227,68 @@ class AdsHub:
_LOGGER.warning("No callback available for this datatype")
notification_item.callback(notification_item.name, value)
class AdsEntity(Entity):
"""Representation of ADS entity."""
def __init__(self, ads_hub, name, ads_var):
"""Initialize ADS binary sensor."""
self._name = name
self._unique_id = ads_var
self._state_dict = {}
self._state_dict[STATE_KEY_STATE] = None
self._ads_hub = ads_hub
self._ads_var = ads_var
self._event = None
async def async_initialize_device(
self, ads_var, plctype, state_key=STATE_KEY_STATE, factor=None):
"""Register device notification."""
def update(name, value):
"""Handle device notifications."""
_LOGGER.debug('Variable %s changed its value to %d', name, value)
if factor is None:
self._state_dict[state_key] = value
else:
self._state_dict[state_key] = value / factor
asyncio.run_coroutine_threadsafe(async_event_set(), self.hass.loop)
self.schedule_update_ha_state()
async def async_event_set():
"""Set event in async context."""
self._event.set()
self._event = asyncio.Event()
await self.hass.async_add_executor_job(
self._ads_hub.add_device_notification,
ads_var, plctype, update)
try:
with async_timeout.timeout(10):
await self._event.wait()
except asyncio.TimeoutError:
_LOGGER.debug('Variable %s: Timeout during first update',
ads_var)
@property
def name(self):
"""Return the default name of the binary sensor."""
return self._name
@property
def unique_id(self):
"""Return an unique identifier for this entity."""
return self._unique_id
@property
def should_poll(self):
"""Return False because entity pushes its state to HA."""
return False
@property
def available(self):
"""Return False if state has not been updated yet."""
return self._state_dict[STATE_KEY_STATE] is not None

View File

@ -8,13 +8,11 @@ from homeassistant.components.binary_sensor import (
from homeassistant.const import CONF_DEVICE_CLASS, CONF_NAME
import homeassistant.helpers.config_validation as cv
from . import CONF_ADS_VAR, DATA_ADS
from . import CONF_ADS_VAR, DATA_ADS, AdsEntity, STATE_KEY_STATE
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'ADS binary sensor'
DEPENDENCIES = ['ads']
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_ADS_VAR): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
@ -34,51 +32,25 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
add_entities([ads_sensor])
class AdsBinarySensor(BinarySensorDevice):
class AdsBinarySensor(AdsEntity, BinarySensorDevice):
"""Representation of ADS binary sensors."""
def __init__(self, ads_hub, name, ads_var, device_class):
"""Initialize ADS binary sensor."""
self._name = name
self._unique_id = ads_var
self._state = False
super().__init__(ads_hub, name, ads_var)
self._device_class = device_class or 'moving'
self._ads_hub = ads_hub
self.ads_var = ads_var
async def async_added_to_hass(self):
"""Register device notification."""
def update(name, value):
"""Handle device notifications."""
_LOGGER.debug('Variable %s changed its value to %d', name, value)
self._state = value
self.schedule_update_ha_state()
self.hass.async_add_job(
self._ads_hub.add_device_notification,
self.ads_var, self._ads_hub.PLCTYPE_BOOL, update)
await self.async_initialize_device(self._ads_var,
self._ads_hub.PLCTYPE_BOOL)
@property
def name(self):
"""Return the default name of the binary sensor."""
return self._name
@property
def unique_id(self):
"""Return an unique identifier for this entity."""
return self._unique_id
def is_on(self):
"""Return True if the entity is on."""
return self._state_dict[STATE_KEY_STATE]
@property
def device_class(self):
"""Return the device class."""
return self._device_class
@property
def is_on(self):
"""Return if the binary sensor is on."""
return self._state
@property
def should_poll(self):
"""Return False because entity pushes its state to HA."""
return False

View File

@ -8,12 +8,11 @@ from homeassistant.components.light import (
from homeassistant.const import CONF_NAME
import homeassistant.helpers.config_validation as cv
from . import CONF_ADS_VAR, CONF_ADS_VAR_BRIGHTNESS, DATA_ADS
from . import CONF_ADS_VAR, CONF_ADS_VAR_BRIGHTNESS, DATA_ADS, \
AdsEntity, STATE_KEY_BRIGHTNESS, STATE_KEY_STATE
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['ads']
DEFAULT_NAME = 'ADS Light'
CONF_ADSVAR_BRIGHTNESS = 'adsvar_brightness'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_ADS_VAR): cv.string,
vol.Optional(CONF_ADS_VAR_BRIGHTNESS): cv.string,
@ -30,91 +29,57 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
name = config.get(CONF_NAME)
add_entities([AdsLight(ads_hub, ads_var_enable, ads_var_brightness,
name)], True)
name)])
class AdsLight(Light):
class AdsLight(AdsEntity, Light):
"""Representation of ADS light."""
def __init__(self, ads_hub, ads_var_enable, ads_var_brightness, name):
"""Initialize AdsLight entity."""
self._ads_hub = ads_hub
self._on_state = False
self._brightness = None
self._name = name
self._unique_id = ads_var_enable
self.ads_var_enable = ads_var_enable
self.ads_var_brightness = ads_var_brightness
super().__init__(ads_hub, name, ads_var_enable)
self._state_dict[STATE_KEY_BRIGHTNESS] = None
self._ads_var_brightness = ads_var_brightness
async def async_added_to_hass(self):
"""Register device notification."""
def update_on_state(name, value):
"""Handle device notifications for state."""
_LOGGER.debug('Variable %s changed its value to %d', name, value)
self._on_state = value
self.schedule_update_ha_state()
await self.async_initialize_device(self._ads_var,
self._ads_hub.PLCTYPE_BOOL)
def update_brightness(name, value):
"""Handle device notification for brightness."""
_LOGGER.debug('Variable %s changed its value to %d', name, value)
self._brightness = value
self.schedule_update_ha_state()
self.hass.async_add_executor_job(
self._ads_hub.add_device_notification,
self.ads_var_enable, self._ads_hub.PLCTYPE_BOOL, update_on_state
)
if self.ads_var_brightness is not None:
self.hass.async_add_executor_job(
self._ads_hub.add_device_notification,
self.ads_var_brightness, self._ads_hub.PLCTYPE_INT,
update_brightness
)
@property
def name(self):
"""Return the name of the device if any."""
return self._name
@property
def unique_id(self):
"""Return an unique identifier for this entity."""
return self._unique_id
if self._ads_var_brightness is not None:
await self.async_initialize_device(self._ads_var_brightness,
self._ads_hub.PLCTYPE_UINT,
STATE_KEY_BRIGHTNESS)
@property
def brightness(self):
"""Return the brightness of the light (0..255)."""
return self._brightness
@property
def is_on(self):
"""Return if light is on."""
return self._on_state
@property
def should_poll(self):
"""Return False because entity pushes its state to HA."""
return False
return self._state_dict[STATE_KEY_BRIGHTNESS]
@property
def supported_features(self):
"""Flag supported features."""
support = 0
if self.ads_var_brightness is not None:
if self._ads_var_brightness is not None:
support = SUPPORT_BRIGHTNESS
return support
@property
def is_on(self):
"""Return True if the entity is on."""
return self._state_dict[STATE_KEY_STATE]
def turn_on(self, **kwargs):
"""Turn the light on or set a specific dimmer value."""
brightness = kwargs.get(ATTR_BRIGHTNESS)
self._ads_hub.write_by_name(self.ads_var_enable, True,
self._ads_hub.write_by_name(self._ads_var, True,
self._ads_hub.PLCTYPE_BOOL)
if self.ads_var_brightness is not None and brightness is not None:
self._ads_hub.write_by_name(self.ads_var_brightness, brightness,
if self._ads_var_brightness is not None and brightness is not None:
self._ads_hub.write_by_name(self._ads_var_brightness, brightness,
self._ads_hub.PLCTYPE_UINT)
def turn_off(self, **kwargs):
"""Turn the light off."""
self._ads_hub.write_by_name(self.ads_var_enable, False,
self._ads_hub.write_by_name(self._ads_var, False,
self._ads_hub.PLCTYPE_BOOL)

View File

@ -0,0 +1,10 @@
{
"domain": "ads",
"name": "Ads",
"documentation": "https://www.home-assistant.io/components/ads",
"requirements": [
"pyads==3.0.7"
],
"dependencies": [],
"codeowners": []
}

View File

@ -7,15 +7,13 @@ from homeassistant.components import ads
from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import CONF_NAME, CONF_UNIT_OF_MEASUREMENT
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
from . import CONF_ADS_FACTOR, CONF_ADS_TYPE, CONF_ADS_VAR
from . import CONF_ADS_FACTOR, CONF_ADS_TYPE, CONF_ADS_VAR, \
AdsEntity, STATE_KEY_STATE
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = "ADS sensor"
DEPENDENCIES = ['ads']
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_ADS_VAR): cv.string,
vol.Optional(CONF_ADS_FACTOR): cv.positive_int,
@ -43,60 +41,31 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
add_entities([entity])
class AdsSensor(Entity):
class AdsSensor(AdsEntity):
"""Representation of an ADS sensor entity."""
def __init__(self, ads_hub, ads_var, ads_type, name, unit_of_measurement,
factor):
"""Initialize AdsSensor entity."""
self._ads_hub = ads_hub
self._name = name
self._unique_id = ads_var
self._value = None
super().__init__(ads_hub, name, ads_var)
self._unit_of_measurement = unit_of_measurement
self.ads_var = ads_var
self.ads_type = ads_type
self.factor = factor
self._ads_type = ads_type
self._factor = factor
async def async_added_to_hass(self):
"""Register device notification."""
def update(name, value):
"""Handle device notifications."""
_LOGGER.debug("Variable %s changed its value to %d", name, value)
# If factor is set use it otherwise not
if self.factor is None:
self._value = value
else:
self._value = value / self.factor
self.schedule_update_ha_state()
self.hass.async_add_job(
self._ads_hub.add_device_notification,
self.ads_var, self._ads_hub.ADS_TYPEMAP[self.ads_type], update
)
@property
def name(self):
"""Return the name of the entity."""
return self._name
@property
def unique_id(self):
"""Return an unique identifier for this entity."""
return self._unique_id
await self.async_initialize_device(
self._ads_var,
self._ads_hub.ADS_TYPEMAP[self._ads_type],
STATE_KEY_STATE,
self._factor)
@property
def state(self):
"""Return the state of the device."""
return self._value
return self._state_dict[STATE_KEY_STATE]
@property
def unit_of_measurement(self):
"""Return the unit of measurement."""
return self._unit_of_measurement
@property
def should_poll(self):
"""Return False because entity pushes its state."""
return False

View File

@ -3,17 +3,14 @@ import logging
import voluptuous as vol
from homeassistant.components.switch import PLATFORM_SCHEMA
from homeassistant.components.switch import SwitchDevice, PLATFORM_SCHEMA
from homeassistant.const import CONF_NAME
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import ToggleEntity
from . import CONF_ADS_VAR, DATA_ADS
from . import CONF_ADS_VAR, DATA_ADS, AdsEntity, STATE_KEY_STATE
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['ads']
DEFAULT_NAME = 'ADS Switch'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@ -29,58 +26,28 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
name = config.get(CONF_NAME)
ads_var = config.get(CONF_ADS_VAR)
add_entities([AdsSwitch(ads_hub, name, ads_var)], True)
add_entities([AdsSwitch(ads_hub, name, ads_var)])
class AdsSwitch(ToggleEntity):
class AdsSwitch(AdsEntity, SwitchDevice):
"""Representation of an ADS switch device."""
def __init__(self, ads_hub, name, ads_var):
"""Initialize the AdsSwitch entity."""
self._ads_hub = ads_hub
self._on_state = False
self._name = name
self._unique_id = ads_var
self.ads_var = ads_var
async def async_added_to_hass(self):
"""Register device notification."""
def update(name, value):
"""Handle device notification."""
_LOGGER.debug("Variable %s changed its value to %d", name, value)
self._on_state = value
self.schedule_update_ha_state()
self.hass.async_add_job(
self._ads_hub.add_device_notification,
self.ads_var, self._ads_hub.PLCTYPE_BOOL, update)
await self.async_initialize_device(self._ads_var,
self._ads_hub.PLCTYPE_BOOL)
@property
def is_on(self):
"""Return if the switch is turned on."""
return self._on_state
@property
def name(self):
"""Return the name of the entity."""
return self._name
@property
def unique_id(self):
"""Return an unique identifier for this entity."""
return self._unique_id
@property
def should_poll(self):
"""Return False because entity pushes its state to HA."""
return False
"""Return True if the entity is on."""
return self._state_dict[STATE_KEY_STATE]
def turn_on(self, **kwargs):
"""Turn the switch on."""
self._ads_hub.write_by_name(
self.ads_var, True, self._ads_hub.PLCTYPE_BOOL)
self._ads_var, True, self._ads_hub.PLCTYPE_BOOL)
def turn_off(self, **kwargs):
"""Turn the switch off."""
self._ads_hub.write_by_name(
self.ads_var, False, self._ads_hub.PLCTYPE_BOOL)
self._ads_var, False, self._ads_hub.PLCTYPE_BOOL)

View File

@ -0,0 +1,2 @@
"""Constants for the Aftership integration."""
DOMAIN = 'aftership'

View File

@ -0,0 +1,10 @@
{
"domain": "aftership",
"name": "Aftership",
"documentation": "https://www.home-assistant.io/components/aftership",
"requirements": [
"pyaftership==0.1.2"
],
"dependencies": [],
"codeowners": []
}

View File

@ -1,9 +1,4 @@
"""
Support for non-delivered packages recorded in AfterShip.
For more details about this platform, please refer to the documentation at
https://www.home-assistant.io/components/sensor.aftership/
"""
"""Support for non-delivered packages recorded in AfterShip."""
from datetime import timedelta
import logging
@ -13,24 +8,44 @@ from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import ATTR_ATTRIBUTION, CONF_API_KEY, CONF_NAME
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.dispatcher import async_dispatcher_send
from homeassistant.helpers.entity import Entity
from homeassistant.util import Throttle
REQUIREMENTS = ['pyaftership==0.1.2']
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
ATTRIBUTION = 'Information provided by AfterShip'
ATTR_TRACKINGS = 'trackings'
BASE = 'https://track.aftership.com/'
CONF_SLUG = 'slug'
CONF_TITLE = 'title'
CONF_TRACKING_NUMBER = 'tracking_number'
DEFAULT_NAME = 'aftership'
UPDATE_TOPIC = DOMAIN + '_update'
ICON = 'mdi:package-variant-closed'
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=30)
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=5)
SERVICE_ADD_TRACKING = 'add_tracking'
SERVICE_REMOVE_TRACKING = 'remove_tracking'
ADD_TRACKING_SERVICE_SCHEMA = vol.Schema(
{
vol.Required(CONF_TRACKING_NUMBER): cv.string,
vol.Optional(CONF_TITLE): cv.string,
vol.Optional(CONF_SLUG): cv.string,
}
)
REMOVE_TRACKING_SERVICE_SCHEMA = vol.Schema(
{vol.Required(CONF_SLUG): cv.string,
vol.Required(CONF_TRACKING_NUMBER): cv.string}
)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_API_KEY): cv.string,
@ -56,7 +71,40 @@ async def async_setup_platform(
aftership.meta)
return
async_add_entities([AfterShipSensor(aftership, name)], True)
instance = AfterShipSensor(aftership, name)
async_add_entities([instance], True)
async def handle_add_tracking(call):
"""Call when a user adds a new Aftership tracking from HASS."""
title = call.data.get(CONF_TITLE)
slug = call.data.get(CONF_SLUG)
tracking_number = call.data[CONF_TRACKING_NUMBER]
await aftership.add_package_tracking(tracking_number, title, slug)
async_dispatcher_send(hass, UPDATE_TOPIC)
hass.services.async_register(
DOMAIN,
SERVICE_ADD_TRACKING,
handle_add_tracking,
schema=ADD_TRACKING_SERVICE_SCHEMA,
)
async def handle_remove_tracking(call):
"""Call when a user removes an Aftership tracking from HASS."""
slug = call.data[CONF_SLUG]
tracking_number = call.data[CONF_TRACKING_NUMBER]
await aftership.remove_package_tracking(slug, tracking_number)
async_dispatcher_send(hass, UPDATE_TOPIC)
hass.services.async_register(
DOMAIN,
SERVICE_REMOVE_TRACKING,
handle_remove_tracking,
schema=REMOVE_TRACKING_SERVICE_SCHEMA,
)
class AfterShipSensor(Entity):
@ -94,8 +142,18 @@ class AfterShipSensor(Entity):
"""Icon to use in the frontend."""
return ICON
async def async_added_to_hass(self):
"""Register callbacks."""
self.hass.helpers.dispatcher.async_dispatcher_connect(
UPDATE_TOPIC, self.force_update)
async def force_update(self):
"""Force update of data."""
await self.async_update(no_throttle=True)
await self.async_update_ha_state()
@Throttle(MIN_TIME_BETWEEN_UPDATES)
async def async_update(self):
async def async_update(self, **kwargs):
"""Get the latest data from the AfterShip API."""
await self.aftership.get_trackings()
@ -109,12 +167,29 @@ class AfterShipSensor(Entity):
status_to_ignore = {'delivered'}
status_counts = {}
trackings = []
not_delivered_count = 0
for tracking in self.aftership.trackings['trackings']:
status = tracking['tag'].lower()
name = tracking['tracking_number']
status_counts[status] = status_counts.get(status, 0)+1
for track in self.aftership.trackings['trackings']:
status = track['tag'].lower()
name = (
track['tracking_number']
if track['title'] is None
else track['title']
)
status_counts[status] = status_counts.get(status, 0) + 1
trackings.append({
'name': name,
'tracking_number': track['tracking_number'],
'slug': track['slug'],
'link': '%s%s/%s' %
(BASE, track['slug'], track['tracking_number']),
'last_update': track['updated_at'],
'expected_delivery': track['expected_delivery'],
'status': track['tag'],
'last_checkpoint': track['checkpoints'][-1]
})
if status not in status_to_ignore:
not_delivered_count += 1
else:
@ -122,7 +197,8 @@ class AfterShipSensor(Entity):
self._attributes = {
ATTR_ATTRIBUTION: ATTRIBUTION,
**status_counts
**status_counts,
ATTR_TRACKINGS: trackings,
}
self._state = not_delivered_count

View File

@ -0,0 +1,24 @@
# Describes the format for available aftership services
add_tracking:
description: Add new tracking to Aftership.
fields:
tracking_number:
description: Tracking number for the new tracking
example: '123456789'
title:
description: A custom title for the new tracking
example: 'Laptop'
slug:
description: Slug (carrier) of the new tracking
example: 'USPS'
remove_tracking:
description: Remove a tracking from Aftership.
fields:
tracking_number:
description: Tracking number of the tracking to remove
example: '123456789'
slug:
description: Slug (carrier) of the tracking to remove
example: 'USPS'

View File

@ -1,9 +1,4 @@
"""
Component for handling Air Quality data for your location.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/air_quality/
"""
"""Component for handling Air Quality data for your location."""
from datetime import timedelta
import logging

View File

@ -0,0 +1,8 @@
{
"domain": "air_quality",
"name": "Air quality",
"documentation": "https://www.home-assistant.io/components/air_quality",
"requirements": [],
"dependencies": [],
"codeowners": []
}

View File

@ -0,0 +1,12 @@
{
"domain": "airvisual",
"name": "Airvisual",
"documentation": "https://www.home-assistant.io/components/airvisual",
"requirements": [
"pyairvisual==3.0.1"
],
"dependencies": [],
"codeowners": [
"@bachya"
]
}

View File

@ -1,9 +1,4 @@
"""
Support for AirVisual air quality sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.airvisual/
"""
"""Support for AirVisual air quality sensors."""
from logging import getLogger
from datetime import timedelta
@ -18,7 +13,6 @@ from homeassistant.helpers import aiohttp_client, config_validation as cv
from homeassistant.helpers.entity import Entity
from homeassistant.util import Throttle
REQUIREMENTS = ['pyairvisual==3.0.1']
_LOGGER = getLogger(__name__)
ATTR_CITY = 'city'

View File

@ -1,9 +1,4 @@
"""
Platform for the Aladdin Connect cover component.
For more details about this platform, please refer to the documentation
https://home-assistant.io/components/cover.aladdin_connect/
"""
"""Platform for the Aladdin Connect cover component."""
import logging
import voluptuous as vol
@ -14,8 +9,6 @@ from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD, STATE_CLOSED,
STATE_OPENING, STATE_CLOSING, STATE_OPEN)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['aladdin_connect==0.3']
_LOGGER = logging.getLogger(__name__)
NOTIFICATION_ID = 'aladdin_notification'

View File

@ -0,0 +1,10 @@
{
"domain": "aladdin_connect",
"name": "Aladdin connect",
"documentation": "https://www.home-assistant.io/components/aladdin_connect",
"requirements": [
"aladdin_connect==0.3"
],
"dependencies": [],
"codeowners": []
}

View File

@ -1,9 +1,4 @@
"""
Component to interface with an alarm control panel.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel/
"""
"""Component to interface with an alarm control panel."""
from datetime import timedelta
import logging

View File

@ -0,0 +1,10 @@
{
"domain": "alarm_control_panel",
"name": "Alarm control panel",
"documentation": "https://www.home-assistant.io/components/alarm_control_panel",
"requirements": [],
"dependencies": [],
"codeowners": [
"@colinodell"
]
}

View File

@ -10,8 +10,6 @@ from homeassistant.helpers.discovery import load_platform
from homeassistant.util import dt as dt_util
from homeassistant.components.binary_sensor import DEVICE_CLASSES_SCHEMA
REQUIREMENTS = ['alarmdecoder==1.13.2']
_LOGGER = logging.getLogger(__name__)
DOMAIN = 'alarmdecoder'

View File

@ -13,8 +13,6 @@ from . import DATA_AD, SIGNAL_PANEL_MESSAGE
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['alarmdecoder']
SERVICE_ALARM_TOGGLE_CHIME = 'alarmdecoder_alarm_toggle_chime'
ALARM_TOGGLE_CHIME_SCHEMA = vol.Schema({
vol.Required(ATTR_CODE): cv.string,

View File

@ -8,8 +8,6 @@ from . import (
CONF_ZONE_RFID, CONF_ZONE_TYPE, CONF_ZONES, SIGNAL_REL_MESSAGE,
SIGNAL_RFX_MESSAGE, SIGNAL_ZONE_FAULT, SIGNAL_ZONE_RESTORE, ZONE_SCHEMA)
DEPENDENCIES = ['alarmdecoder']
_LOGGER = logging.getLogger(__name__)
ATTR_RF_BIT0 = 'rf_bit0'

View File

@ -0,0 +1,10 @@
{
"domain": "alarmdecoder",
"name": "Alarmdecoder",
"documentation": "https://www.home-assistant.io/components/alarmdecoder",
"requirements": [
"alarmdecoder==1.13.2"
],
"dependencies": [],
"codeowners": []
}

View File

@ -7,8 +7,6 @@ from . import SIGNAL_PANEL_MESSAGE
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['alarmdecoder']
def setup_platform(hass, config, add_entities, discovery_info=None):
"""Set up for AlarmDecoder sensor devices."""

View File

@ -1,9 +1,4 @@
"""
Interfaces with Alarm.com alarm control panels.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.alarmdotcom/
"""
"""Interfaces with Alarm.com alarm control panels."""
import logging
import re
@ -17,8 +12,6 @@ from homeassistant.const import (
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['pyalarmdotcom==0.3.2']
_LOGGER = logging.getLogger(__name__)
DEFAULT_NAME = 'Alarm.com'

View File

@ -0,0 +1,10 @@
{
"domain": "alarmdotcom",
"name": "Alarmdotcom",
"documentation": "https://www.home-assistant.io/components/alarmdotcom",
"requirements": [
"pyalarmdotcom==0.3.2"
],
"dependencies": [],
"codeowners": []
}

View File

@ -0,0 +1,8 @@
{
"domain": "alert",
"name": "Alert",
"documentation": "https://www.home-assistant.io/components/alert",
"requirements": [],
"dependencies": [],
"codeowners": []
}

View File

@ -17,8 +17,6 @@ _LOGGER = logging.getLogger(__name__)
CONF_FLASH_BRIEFINGS = 'flash_briefings'
CONF_SMART_HOME = 'smart_home'
DEPENDENCIES = ['http']
ALEXA_ENTITY_SCHEMA = vol.Schema({
vol.Optional(smart_home.CONF_DESCRIPTION): cv.string,
vol.Optional(smart_home.CONF_DISPLAY_CATEGORIES): cv.string,

View File

@ -0,0 +1,10 @@
{
"domain": "alexa",
"name": "Alexa",
"documentation": "https://www.home-assistant.io/components/alexa",
"requirements": [],
"dependencies": [
"http"
],
"codeowners": []
}

View File

@ -0,0 +1,12 @@
{
"domain": "alpha_vantage",
"name": "Alpha vantage",
"documentation": "https://www.home-assistant.io/components/alpha_vantage",
"requirements": [
"alpha_vantage==2.1.0"
],
"dependencies": [],
"codeowners": [
"@fabaff"
]
}

View File

@ -1,9 +1,4 @@
"""
Stock market information from Alpha Vantage.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/sensor.alpha_vantage/
"""
"""Stock market information from Alpha Vantage."""
from datetime import timedelta
import logging
@ -15,8 +10,6 @@ from homeassistant.const import (
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import Entity
REQUIREMENTS = ['alpha_vantage==2.1.0']
_LOGGER = logging.getLogger(__name__)
ATTR_CLOSE = 'close'

View File

@ -0,0 +1,12 @@
{
"domain": "amazon_polly",
"name": "Amazon polly",
"documentation": "https://www.home-assistant.io/components/amazon_polly",
"requirements": [
"boto3==1.9.16"
],
"dependencies": [],
"codeowners": [
"@robbiet480"
]
}

View File

@ -1,9 +1,4 @@
"""
Support for the Amazon Polly text to speech service.
For more details about this component, please refer to the documentation at
https://home-assistant.io/components/tts.amazon_polly/
"""
"""Support for the Amazon Polly text to speech service."""
import logging
import voluptuous as vol
@ -11,8 +6,6 @@ import voluptuous as vol
from homeassistant.components.tts import PLATFORM_SCHEMA, Provider
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['boto3==1.9.16']
_LOGGER = logging.getLogger(__name__)
CONF_REGION = 'region_name'

View File

@ -1,9 +1,19 @@
{
"config": {
"error": {
"identifier_exists": "La clave API y/o la clave de aplicaci\u00f3n ya est\u00e1 registrada",
"invalid_key": "Clave API y/o clave de aplicaci\u00f3n no v\u00e1lida",
"no_devices": "No se han encontrado dispositivos en la cuenta"
},
"step": {
"user": {
"data": {
"api_key": "Clave API",
"app_key": "Clave de aplicaci\u00f3n"
},
"title": "Completa tu informaci\u00f3n"
}
}
},
"title": "Ambient PWS"
}
}

View File

@ -13,6 +13,7 @@
},
"title": "Veuillez saisir vos informations"
}
}
},
"title": "Ambient PWS"
}
}

View File

@ -11,7 +11,7 @@
"api_key": "API \ud0a4",
"app_key": "Application \ud0a4"
},
"title": "\uc0ac\uc6a9\uc790 \uc815\ubcf4\ub97c \uc785\ub825\ud574\uc8fc\uc138\uc694"
"title": "\uc0ac\uc6a9\uc790 \uc815\ubcf4 \uc785\ub825"
}
},
"title": "Ambient PWS"

View File

@ -1,5 +1,8 @@
{
"config": {
"error": {
"no_devices": "\u0e44\u0e21\u0e48\u0e1e\u0e1a\u0e2d\u0e38\u0e1b\u0e01\u0e23\u0e13\u0e4c\u0e43\u0e14\u0e46 \u0e43\u0e19\u0e1a\u0e31\u0e0d\u0e0a\u0e35\u0e40\u0e25\u0e22"
},
"step": {
"user": {
"data": {

View File

@ -20,8 +20,6 @@ from .const import (
ATTR_LAST_DATA, CONF_APP_KEY, DATA_CLIENT, DOMAIN, TOPIC_UPDATE,
TYPE_BINARY_SENSOR, TYPE_SENSOR)
REQUIREMENTS = ['aioambient==0.2.0']
_LOGGER = logging.getLogger(__name__)
DATA_CONFIG = 'config'
@ -329,6 +327,8 @@ class AmbientStation:
"""Define a handler to fire when the websocket is connected."""
_LOGGER.info('Connected to websocket')
_LOGGER.debug('Watchdog starting')
if self._watchdog_listener:
self._watchdog_listener()
self._watchdog_listener = async_call_later(
self._hass, DEFAULT_WATCHDOG_SECONDS, _ws_reconnect)

View File

@ -12,8 +12,6 @@ from .const import ATTR_LAST_DATA, DATA_CLIENT, DOMAIN, TYPE_BINARY_SENSOR
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['ambient_station']
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):

View File

@ -0,0 +1,12 @@
{
"domain": "ambient_station",
"name": "Ambient station",
"documentation": "https://www.home-assistant.io/components/ambient_station",
"requirements": [
"aioambient==0.3.0"
],
"dependencies": [],
"codeowners": [
"@bachya"
]
}

View File

@ -8,8 +8,6 @@ from .const import ATTR_LAST_DATA, DATA_CLIENT, DOMAIN, TYPE_SENSOR
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['ambient_station']
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):

View File

@ -7,14 +7,11 @@ import voluptuous as vol
from homeassistant.const import (
CONF_NAME, CONF_HOST, CONF_PORT, CONF_USERNAME, CONF_PASSWORD,
CONF_SENSORS, CONF_SWITCHES, CONF_SCAN_INTERVAL, HTTP_BASIC_AUTHENTICATION)
CONF_BINARY_SENSORS, CONF_SENSORS, CONF_SWITCHES, CONF_SCAN_INTERVAL,
HTTP_BASIC_AUTHENTICATION)
from homeassistant.helpers import discovery
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['amcrest==1.2.7']
DEPENDENCIES = ['ffmpeg']
_LOGGER = logging.getLogger(__name__)
CONF_AUTHENTICATION = 'authentication'
@ -52,9 +49,14 @@ STREAM_SOURCE_LIST = {
'rtsp': 2,
}
BINARY_SENSORS = {
'motion_detected': 'Motion Detected'
}
# Sensor types are defined like: Name, units, icon
SENSOR_MOTION_DETECTOR = 'motion_detector'
SENSORS = {
'motion_detector': ['Motion Detected', None, 'mdi:run'],
SENSOR_MOTION_DETECTOR: ['Motion Detected', None, 'mdi:run'],
'sdcard': ['SD Used', '%', 'mdi:sd'],
'ptz_preset': ['PTZ Preset', None, 'mdi:camera-iris'],
}
@ -65,28 +67,49 @@ SWITCHES = {
'motion_recording': ['Motion Recording', 'mdi:record-rec']
}
def _deprecated_sensors(value):
if SENSOR_MOTION_DETECTOR in value:
_LOGGER.warning(
'sensors option %s is deprecated. '
'Please remove from your configuration and '
'use binary_sensors option motion_detected instead.',
SENSOR_MOTION_DETECTOR)
return value
def _has_unique_names(value):
names = [camera[CONF_NAME] for camera in value]
vol.Schema(vol.Unique())(names)
return value
AMCREST_SCHEMA = vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_AUTHENTICATION, default=HTTP_BASIC_AUTHENTICATION):
vol.All(vol.In(AUTHENTICATION_LIST)),
vol.Optional(CONF_RESOLUTION, default=DEFAULT_RESOLUTION):
vol.All(vol.In(RESOLUTION_LIST)),
vol.Optional(CONF_STREAM_SOURCE, default=DEFAULT_STREAM_SOURCE):
vol.All(vol.In(STREAM_SOURCE_LIST)),
vol.Optional(CONF_FFMPEG_ARGUMENTS, default=DEFAULT_ARGUMENTS):
cv.string,
vol.Optional(CONF_SCAN_INTERVAL, default=SCAN_INTERVAL):
cv.time_period,
vol.Optional(CONF_BINARY_SENSORS):
vol.All(cv.ensure_list, [vol.In(BINARY_SENSORS)]),
vol.Optional(CONF_SENSORS):
vol.All(cv.ensure_list, [vol.In(SENSORS)], _deprecated_sensors),
vol.Optional(CONF_SWITCHES):
vol.All(cv.ensure_list, [vol.In(SWITCHES)]),
})
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.All(cv.ensure_list, [vol.Schema({
vol.Required(CONF_HOST): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
vol.Optional(CONF_AUTHENTICATION, default=HTTP_BASIC_AUTHENTICATION):
vol.All(vol.In(AUTHENTICATION_LIST)),
vol.Optional(CONF_RESOLUTION, default=DEFAULT_RESOLUTION):
vol.All(vol.In(RESOLUTION_LIST)),
vol.Optional(CONF_STREAM_SOURCE, default=DEFAULT_STREAM_SOURCE):
vol.All(vol.In(STREAM_SOURCE_LIST)),
vol.Optional(CONF_FFMPEG_ARGUMENTS, default=DEFAULT_ARGUMENTS):
cv.string,
vol.Optional(CONF_SCAN_INTERVAL, default=SCAN_INTERVAL):
cv.time_period,
vol.Optional(CONF_SENSORS):
vol.All(cv.ensure_list, [vol.In(SENSORS)]),
vol.Optional(CONF_SWITCHES):
vol.All(cv.ensure_list, [vol.In(SWITCHES)]),
})])
DOMAIN: vol.All(cv.ensure_list, [AMCREST_SCHEMA], _has_unique_names)
}, extra=vol.ALLOW_EXTRA)
@ -94,20 +117,24 @@ def setup(hass, config):
"""Set up the Amcrest IP Camera component."""
from amcrest import AmcrestCamera, AmcrestError
hass.data[DATA_AMCREST] = {}
hass.data.setdefault(DATA_AMCREST, {})
amcrest_cams = config[DOMAIN]
for device in amcrest_cams:
name = device[CONF_NAME]
username = device[CONF_USERNAME]
password = device[CONF_PASSWORD]
try:
camera = AmcrestCamera(device.get(CONF_HOST),
device.get(CONF_PORT),
device.get(CONF_USERNAME),
device.get(CONF_PASSWORD)).camera
camera = AmcrestCamera(device[CONF_HOST],
device[CONF_PORT],
username,
password).camera
# pylint: disable=pointless-statement
camera.current_time
except AmcrestError as ex:
_LOGGER.error("Unable to connect to Amcrest camera: %s", str(ex))
_LOGGER.error("Unable to connect to %s camera: %s", name, str(ex))
hass.components.persistent_notification.create(
'Error: {}<br />'
'You will need to restart hass after fixing.'
@ -116,23 +143,19 @@ def setup(hass, config):
notification_id=NOTIFICATION_ID)
continue
ffmpeg_arguments = device.get(CONF_FFMPEG_ARGUMENTS)
name = device.get(CONF_NAME)
resolution = RESOLUTION_LIST[device.get(CONF_RESOLUTION)]
ffmpeg_arguments = device[CONF_FFMPEG_ARGUMENTS]
resolution = RESOLUTION_LIST[device[CONF_RESOLUTION]]
binary_sensors = device.get(CONF_BINARY_SENSORS)
sensors = device.get(CONF_SENSORS)
switches = device.get(CONF_SWITCHES)
stream_source = STREAM_SOURCE_LIST[device.get(CONF_STREAM_SOURCE)]
username = device.get(CONF_USERNAME)
password = device.get(CONF_PASSWORD)
stream_source = STREAM_SOURCE_LIST[device[CONF_STREAM_SOURCE]]
# currently aiohttp only works with basic authentication
# only valid for mjpeg streaming
if username is not None and password is not None:
if device.get(CONF_AUTHENTICATION) == HTTP_BASIC_AUTHENTICATION:
authentication = aiohttp.BasicAuth(username, password)
else:
authentication = None
if device[CONF_AUTHENTICATION] == HTTP_BASIC_AUTHENTICATION:
authentication = aiohttp.BasicAuth(username, password)
else:
authentication = None
hass.data[DATA_AMCREST][name] = AmcrestDevice(
camera, name, authentication, ffmpeg_arguments, stream_source,
@ -143,6 +166,13 @@ def setup(hass, config):
CONF_NAME: name,
}, config)
if binary_sensors:
discovery.load_platform(
hass, 'binary_sensor', DOMAIN, {
CONF_NAME: name,
CONF_BINARY_SENSORS: binary_sensors
}, config)
if sensors:
discovery.load_platform(
hass, 'sensor', DOMAIN, {
@ -157,7 +187,7 @@ def setup(hass, config):
CONF_SWITCHES: switches
}, config)
return True
return len(hass.data[DATA_AMCREST]) >= 1
class AmcrestDevice:

View File

@ -0,0 +1,69 @@
"""Suppoort for Amcrest IP camera binary sensors."""
from datetime import timedelta
import logging
from homeassistant.components.binary_sensor import (
BinarySensorDevice, DEVICE_CLASS_MOTION)
from homeassistant.const import CONF_NAME, CONF_BINARY_SENSORS
from . import DATA_AMCREST, BINARY_SENSORS
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(seconds=5)
async def async_setup_platform(hass, config, async_add_devices,
discovery_info=None):
"""Set up a binary sensor for an Amcrest IP Camera."""
if discovery_info is None:
return
device_name = discovery_info[CONF_NAME]
binary_sensors = discovery_info[CONF_BINARY_SENSORS]
amcrest = hass.data[DATA_AMCREST][device_name]
amcrest_binary_sensors = []
for sensor_type in binary_sensors:
amcrest_binary_sensors.append(
AmcrestBinarySensor(amcrest.name, amcrest.device, sensor_type))
async_add_devices(amcrest_binary_sensors, True)
class AmcrestBinarySensor(BinarySensorDevice):
"""Binary sensor for Amcrest camera."""
def __init__(self, name, camera, sensor_type):
"""Initialize entity."""
self._name = '{} {}'.format(name, BINARY_SENSORS[sensor_type])
self._camera = camera
self._sensor_type = sensor_type
self._state = None
@property
def name(self):
"""Return entity name."""
return self._name
@property
def is_on(self):
"""Return if entity is on."""
return self._state
@property
def device_class(self):
"""Return device class."""
return DEVICE_CLASS_MOTION
def update(self):
"""Update entity."""
from amcrest import AmcrestError
_LOGGER.debug('Pulling data from %s binary sensor', self._name)
try:
self._state = self._camera.is_motion_detected
except AmcrestError as error:
_LOGGER.error(
'Could not update %s binary sensor due to error: %s',
self.name, error)

View File

@ -3,7 +3,7 @@ import asyncio
import logging
from homeassistant.components.camera import (
Camera, SUPPORT_STREAM)
Camera, SUPPORT_ON_OFF, SUPPORT_STREAM)
from homeassistant.components.ffmpeg import DATA_FFMPEG
from homeassistant.const import CONF_NAME
from homeassistant.helpers.aiohttp_client import (
@ -12,8 +12,6 @@ from homeassistant.helpers.aiohttp_client import (
from . import DATA_AMCREST, STREAM_SOURCE_LIST, TIMEOUT
DEPENDENCIES = ['amcrest', 'ffmpeg']
_LOGGER = logging.getLogger(__name__)
@ -28,8 +26,6 @@ async def async_setup_platform(hass, config, async_add_entities,
async_add_entities([AmcrestCam(hass, amcrest)], True)
return True
class AmcrestCam(Camera):
"""An implementation of an Amcrest IP camera."""
@ -39,18 +35,23 @@ class AmcrestCam(Camera):
super(AmcrestCam, self).__init__()
self._name = amcrest.name
self._camera = amcrest.device
self._base_url = self._camera.get_base_url()
self._ffmpeg = hass.data[DATA_FFMPEG]
self._ffmpeg_arguments = amcrest.ffmpeg_arguments
self._stream_source = amcrest.stream_source
self._resolution = amcrest.resolution
self._token = self._auth = amcrest.authentication
self._is_recording = False
self._model = None
self._snapshot_lock = asyncio.Lock()
async def async_camera_image(self):
"""Return a still image response from the camera."""
from amcrest import AmcrestError
if not self.is_on:
_LOGGER.error(
'Attempt to take snaphot when %s camera is off', self.name)
return None
async with self._snapshot_lock:
try:
# Send the request to snap a picture and return raw jpg data
@ -59,7 +60,8 @@ class AmcrestCam(Camera):
return response.data
except AmcrestError as error:
_LOGGER.error(
'Could not get camera image due to error %s', error)
'Could not get image from %s camera due to error: %s',
self.name, error)
return None
async def handle_async_mjpeg_stream(self, request):
@ -94,6 +96,8 @@ class AmcrestCam(Camera):
finally:
await stream.close()
# Entity property overrides
@property
def name(self):
"""Return the name of this camera."""
@ -102,9 +106,80 @@ class AmcrestCam(Camera):
@property
def supported_features(self):
"""Return supported features."""
return SUPPORT_STREAM
return SUPPORT_ON_OFF | SUPPORT_STREAM
# Camera property overrides
@property
def is_recording(self):
"""Return true if the device is recording."""
return self._is_recording
@property
def brand(self):
"""Return the camera brand."""
return 'Amcrest'
@property
def model(self):
"""Return the camera model."""
return self._model
@property
def stream_source(self):
"""Return the source of the stream."""
return self._camera.rtsp_url(typeno=self._resolution)
@property
def is_on(self):
"""Return true if on."""
return self.is_streaming
# Other Entity method overrides
def update(self):
"""Update entity status."""
from amcrest import AmcrestError
_LOGGER.debug('Pulling data from %s camera', self.name)
if self._model is None:
try:
self._model = self._camera.device_type.split('=')[-1].strip()
except AmcrestError as error:
_LOGGER.error(
'Could not get %s camera model due to error: %s',
self.name, error)
self._model = ''
try:
self.is_streaming = self._camera.video_enabled
self._is_recording = self._camera.record_mode == 'Manual'
except AmcrestError as error:
_LOGGER.error(
'Could not get %s camera attributes due to error: %s',
self.name, error)
# Other Camera method overrides
def turn_off(self):
"""Turn off camera."""
self._enable_video_stream(False)
def turn_on(self):
"""Turn on camera."""
self._enable_video_stream(True)
# Utility methods
def _enable_video_stream(self, enable):
"""Enable or disable camera video stream."""
from amcrest import AmcrestError
try:
self._camera.video_enabled = enable
except AmcrestError as error:
_LOGGER.error(
'Could not %s %s camera video stream due to error: %s',
'enable' if enable else 'disable', self.name, error)
else:
self.is_streaming = enable
self.schedule_update_ha_state()

View File

@ -0,0 +1,12 @@
{
"domain": "amcrest",
"name": "Amcrest",
"documentation": "https://www.home-assistant.io/components/amcrest",
"requirements": [
"amcrest==1.3.0"
],
"dependencies": [
"ffmpeg"
],
"codeowners": []
}

View File

@ -7,8 +7,6 @@ from homeassistant.helpers.entity import Entity
from . import DATA_AMCREST, SENSORS
DEPENDENCIES = ['amcrest']
_LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(seconds=10)
@ -30,7 +28,6 @@ async def async_setup_platform(
AmcrestSensor(amcrest.name, amcrest.device, sensor_type))
async_add_entities(amcrest_sensors, True)
return True
class AmcrestSensor(Entity):
@ -75,19 +72,6 @@ class AmcrestSensor(Entity):
"""Get the latest data and updates the state."""
_LOGGER.debug("Pulling data from %s sensor.", self._name)
try:
version, build_date = self._camera.software_information
self._attrs['Build Date'] = build_date.split('=')[-1]
self._attrs['Version'] = version.split('=')[-1]
except ValueError:
self._attrs['Build Date'] = 'Not Available'
self._attrs['Version'] = 'Not Available'
try:
self._attrs['Serial Number'] = self._camera.serial_number
except ValueError:
self._attrs['Serial Number'] = 'Not Available'
if self._sensor_type == 'motion_detector':
self._state = self._camera.is_motion_detected
self._attrs['Record Mode'] = self._camera.record_mode

View File

@ -8,8 +8,6 @@ from . import DATA_AMCREST, SWITCHES
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['amcrest']
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):

View File

@ -0,0 +1 @@
"""The Ampio component."""

View File

@ -0,0 +1,95 @@
"""Support for Ampio Air Quality data."""
from datetime import timedelta
import logging
import voluptuous as vol
from homeassistant.components.air_quality import (
PLATFORM_SCHEMA, AirQualityEntity)
from homeassistant.const import CONF_NAME
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
from homeassistant.util import Throttle
_LOGGER = logging.getLogger(__name__)
ATTRIBUTION = 'Data provided by Ampio'
CONF_STATION_ID = 'station_id'
SCAN_INTERVAL = timedelta(minutes=10)
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_STATION_ID): cv.string,
vol.Optional(CONF_NAME): cv.string,
})
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):
"""Set up the Ampio Smog air quality platform."""
from asmog import AmpioSmog
name = config.get(CONF_NAME)
station_id = config[CONF_STATION_ID]
session = async_get_clientsession(hass)
api = AmpioSmogMapData(AmpioSmog(station_id, hass.loop, session))
await api.async_update()
if not api.api.data:
_LOGGER.error("Station %s is not available", station_id)
return
async_add_entities([AmpioSmogQuality(api, station_id, name)], True)
class AmpioSmogQuality(AirQualityEntity):
"""Implementation of an Ampio Smog air quality entity."""
def __init__(self, api, station_id, name):
"""Initialize the air quality entity."""
self._ampio = api
self._station_id = station_id
self._name = name or api.api.name
@property
def name(self):
"""Return the name of the air quality entity."""
return self._name
@property
def unique_id(self):
"""Return unique_name."""
return "ampio_smog_{}".format(self._station_id)
@property
def particulate_matter_2_5(self):
"""Return the particulate matter 2.5 level."""
return self._ampio.api.pm2_5
@property
def particulate_matter_10(self):
"""Return the particulate matter 10 level."""
return self._ampio.api.pm10
@property
def attribution(self):
"""Return the attribution."""
return ATTRIBUTION
async def async_update(self):
"""Get the latest data from the AmpioMap API."""
await self._ampio.async_update()
class AmpioSmogMapData:
"""Get the latest data and update the states."""
def __init__(self, api):
"""Initialize the data object."""
self.api = api
@Throttle(SCAN_INTERVAL)
async def async_update(self):
"""Get the latest data from AmpioMap."""
await self.api.get_data()

View File

@ -0,0 +1,10 @@
{
"domain": "ampio",
"name": "Ampio",
"documentation": "https://www.home-assistant.io/components/ampio",
"requirements": [
"asmog==0.0.6"
],
"dependencies": [],
"codeowners": []
}

View File

@ -21,8 +21,6 @@ from homeassistant.util.dt import utcnow
from homeassistant.components.mjpeg.camera import (
CONF_MJPEG_URL, CONF_STILL_IMAGE_URL)
REQUIREMENTS = ['pydroid-ipcam==0.8']
_LOGGER = logging.getLogger(__name__)
ATTR_AUD_CONNS = 'Audio Connections'

View File

@ -3,8 +3,6 @@ from homeassistant.components.binary_sensor import BinarySensorDevice
from . import CONF_HOST, CONF_NAME, DATA_IP_WEBCAM, KEY_MAP, AndroidIPCamEntity
DEPENDENCIES = ['android_ip_webcam']
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):

View File

@ -0,0 +1,10 @@
{
"domain": "android_ip_webcam",
"name": "Android ip webcam",
"documentation": "https://www.home-assistant.io/components/android_ip_webcam",
"requirements": [
"pydroid-ipcam==0.8"
],
"dependencies": [],
"codeowners": []
}

View File

@ -5,8 +5,6 @@ from . import (
CONF_HOST, CONF_NAME, CONF_SENSORS, DATA_IP_WEBCAM, ICON_MAP, KEY_MAP,
AndroidIPCamEntity)
DEPENDENCIES = ['android_ip_webcam']
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):

View File

@ -5,8 +5,6 @@ from . import (
CONF_HOST, CONF_NAME, CONF_SWITCHES, DATA_IP_WEBCAM, ICON_MAP, KEY_MAP,
AndroidIPCamEntity)
DEPENDENCIES = ['android_ip_webcam']
async def async_setup_platform(
hass, config, async_add_entities, discovery_info=None):

View File

@ -1,6 +1 @@
"""
Support for functionality to interact with Android TV and Fire TV devices.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/media_player.androidtv/
"""
"""Support for functionality to interact with Android TV/Fire TV devices."""

View File

@ -0,0 +1,10 @@
{
"domain": "androidtv",
"name": "Androidtv",
"documentation": "https://www.home-assistant.io/components/androidtv",
"requirements": [
"androidtv==0.0.15"
],
"dependencies": [],
"codeowners": []
}

View File

@ -1,9 +1,4 @@
"""
Support for functionality to interact with Android TV and Fire TV devices.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/media_player.androidtv/
"""
"""Support for functionality to interact with Android TV / Fire TV devices."""
import functools
import logging
import voluptuous as vol
@ -18,12 +13,11 @@ from homeassistant.const import (
ATTR_COMMAND, ATTR_ENTITY_ID, CONF_DEVICE_CLASS, CONF_HOST, CONF_NAME,
CONF_PORT, STATE_IDLE, STATE_OFF, STATE_PAUSED, STATE_PLAYING,
STATE_STANDBY)
from homeassistant.exceptions import PlatformNotReady
import homeassistant.helpers.config_validation as cv
ANDROIDTV_DOMAIN = 'androidtv'
REQUIREMENTS = ['androidtv==0.0.14']
_LOGGER = logging.getLogger(__name__)
SUPPORT_ANDROIDTV = SUPPORT_PAUSE | SUPPORT_PLAY | \
@ -125,7 +119,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
_LOGGER.warning("Could not connect to %s at %s%s",
device_name, host, adb_log)
return
raise PlatformNotReady
if host in hass.data[ANDROIDTV_DOMAIN]:
_LOGGER.warning("Platform already setup on %s, skipping", host)
@ -298,12 +292,12 @@ class ADBDevice(MediaPlayerDevice):
@adb_decorator()
def media_previous_track(self):
"""Send previous track command (results in rewind)."""
self.aftv.media_previous()
self.aftv.media_previous_track()
@adb_decorator()
def media_next_track(self):
"""Send next track command (results in fast-forward)."""
self.aftv.media_next()
self.aftv.media_next_track()
@adb_decorator()
def adb_command(self, cmd):
@ -328,11 +322,10 @@ class AndroidTVDevice(ADBDevice):
turn_off_command)
self._device = None
self._muted = None
self._device_properties = self.aftv.device_properties
self._unique_id = 'androidtv-{}-{}'.format(
name, self._device_properties['serialno'])
self._volume = None
self._is_volume_muted = None
self._unique_id = self._device_properties.get('serialno')
self._volume_level = None
@adb_decorator(override_available=True)
def update(self):
@ -349,16 +342,16 @@ class AndroidTVDevice(ADBDevice):
if not self._available:
return
# Get the `state`, `current_app`, and `running_apps`.
state, self._current_app, self._device, self._muted, self._volume = \
self.aftv.update()
# Get the updated state and attributes.
state, self._current_app, self._device, self._is_volume_muted, \
self._volume_level = self.aftv.update()
self._state = ANDROIDTV_STATES[state]
@property
def is_volume_muted(self):
"""Boolean if volume is currently muted."""
return self._muted
return self._is_volume_muted
@property
def source(self):
@ -378,7 +371,7 @@ class AndroidTVDevice(ADBDevice):
@property
def volume_level(self):
"""Return the volume level."""
return self._volume
return self._volume_level
@adb_decorator()
def media_stop(self):
@ -393,12 +386,12 @@ class AndroidTVDevice(ADBDevice):
@adb_decorator()
def volume_down(self):
"""Send volume down command."""
self.aftv.volume_down()
self._volume_level = self.aftv.volume_down(self._volume_level)
@adb_decorator()
def volume_up(self):
"""Send volume up command."""
self.aftv.volume_up()
self._volume_level = self.aftv.volume_up(self._volume_level)
class FireTVDevice(ADBDevice):

View File

@ -0,0 +1,10 @@
{
"domain": "anel_pwrctrl",
"name": "Anel pwrctrl",
"documentation": "https://www.home-assistant.io/components/anel_pwrctrl",
"requirements": [
"anel_pwrctrl-homeassistant==0.0.1.dev2"
],
"dependencies": [],
"codeowners": []
}

View File

@ -1,9 +1,4 @@
"""
Support for ANEL PwrCtrl switches.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/switch.pwrctrl/
"""
"""Support for ANEL PwrCtrl switches."""
import logging
import socket
from datetime import timedelta
@ -15,8 +10,6 @@ from homeassistant.components.switch import (SwitchDevice, PLATFORM_SCHEMA)
from homeassistant.const import (CONF_HOST, CONF_PASSWORD, CONF_USERNAME)
from homeassistant.util import Throttle
REQUIREMENTS = ['anel_pwrctrl-homeassistant==0.0.1.dev2']
_LOGGER = logging.getLogger(__name__)
CONF_PORT_RECV = 'port_recv'

View File

@ -0,0 +1,10 @@
{
"domain": "anthemav",
"name": "Anthemav",
"documentation": "https://www.home-assistant.io/components/anthemav",
"requirements": [
"anthemav==1.1.10"
],
"dependencies": [],
"codeowners": []
}

View File

@ -1,9 +1,4 @@
"""
Support for Anthem Network Receivers and Processors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/media_player.anthemav/
"""
"""Support for Anthem Network Receivers and Processors."""
import logging
import voluptuous as vol
@ -18,8 +13,6 @@ from homeassistant.const import (
STATE_ON)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['anthemav==1.1.10']
_LOGGER = logging.getLogger(__name__)
DOMAIN = 'anthemav'

View File

@ -8,8 +8,6 @@ from homeassistant.const import (CONF_HOST, CONF_PORT)
import homeassistant.helpers.config_validation as cv
from homeassistant.util import Throttle
REQUIREMENTS = ['apcaccess==0.0.13']
_LOGGER = logging.getLogger(__name__)
CONF_TYPE = 'type'

View File

@ -8,8 +8,6 @@ import homeassistant.helpers.config_validation as cv
from homeassistant.components import apcupsd
DEFAULT_NAME = 'UPS Online Status'
DEPENDENCIES = [apcupsd.DOMAIN]
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
})

View File

@ -0,0 +1,10 @@
{
"domain": "apcupsd",
"name": "Apcupsd",
"documentation": "https://www.home-assistant.io/components/apcupsd",
"requirements": [
"apcaccess==0.0.13"
],
"dependencies": [],
"codeowners": []
}

View File

@ -11,8 +11,6 @@ from homeassistant.helpers.entity import Entity
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = [apcupsd.DOMAIN]
SENSOR_PREFIX = 'UPS '
SENSOR_TYPES = {
'alarmdel': ['Alarm Delay', '', 'mdi:alarm'],

View File

@ -33,8 +33,6 @@ ATTR_REQUIRES_API_PASSWORD = 'requires_api_password'
ATTR_VERSION = 'version'
DOMAIN = 'api'
DEPENDENCIES = ['http']
STREAM_PING_PAYLOAD = 'ping'
STREAM_PING_INTERVAL = 50 # seconds

View File

@ -0,0 +1,12 @@
{
"domain": "api",
"name": "Home Assistant API",
"documentation": "https://www.home-assistant.io/components/api",
"requirements": [],
"dependencies": [
"http"
],
"codeowners": [
"@home-assistant/core"
]
}

View File

@ -1 +0,0 @@
"""The api_streams component."""

View File

@ -0,0 +1,10 @@
{
"domain": "apns",
"name": "Apns",
"documentation": "https://www.home-assistant.io/components/apns",
"requirements": [
"apns2==0.3.0"
],
"dependencies": [],
"codeowners": []
}

View File

@ -1,9 +1,4 @@
"""
APNS Notification platform.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/notify.apns/
"""
"""APNS Notification platform."""
import logging
import os
@ -18,8 +13,6 @@ from homeassistant.helpers.event import track_state_change
from homeassistant.components.notify import (
ATTR_DATA, ATTR_TARGET, DOMAIN, PLATFORM_SCHEMA, BaseNotificationService)
REQUIREMENTS = ['apns2==0.3.0']
APNS_DEVICES = 'apns.yaml'
CONF_CERTFILE = 'cert_file'
CONF_TOPIC = 'topic'

View File

@ -11,8 +11,6 @@ from homeassistant.helpers import discovery
from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['pyatv==0.3.12']
_LOGGER = logging.getLogger(__name__)
DOMAIN = 'apple_tv'

View File

@ -0,0 +1,10 @@
{
"domain": "apple_tv",
"name": "Apple tv",
"documentation": "https://www.home-assistant.io/components/apple_tv",
"requirements": [
"pyatv==0.3.12"
],
"dependencies": ["configurator"],
"codeowners": []
}

View File

@ -14,8 +14,6 @@ import homeassistant.util.dt as dt_util
from . import ATTR_ATV, ATTR_POWER, DATA_APPLE_TV, DATA_ENTITIES
DEPENDENCIES = ['apple_tv']
_LOGGER = logging.getLogger(__name__)
SUPPORT_APPLE_TV = SUPPORT_TURN_ON | SUPPORT_TURN_OFF | SUPPORT_PLAY_MEDIA | \

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