mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 15:17:35 +00:00
commit
8ae2ce2299
@ -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.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 >>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>>
|
<<# 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:
|
- save_cache:
|
||||||
paths:
|
paths:
|
||||||
- ./venv
|
- ./venv
|
||||||
@ -99,6 +100,13 @@ jobs:
|
|||||||
mypy $TYPING_FILES
|
mypy $TYPING_FILES
|
||||||
|
|
||||||
- install
|
- install
|
||||||
|
|
||||||
|
- run:
|
||||||
|
name: validate manifests
|
||||||
|
command: |
|
||||||
|
. venv/bin/activate
|
||||||
|
python -m script.hassfest validate
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: run gen_requirements_all
|
name: run gen_requirements_all
|
||||||
command: |
|
command: |
|
||||||
@ -139,6 +147,7 @@ jobs:
|
|||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
PYFILES=$(circleci tests glob "homeassistant/**/*.py" | circleci tests split)
|
PYFILES=$(circleci tests glob "homeassistant/**/*.py" | circleci tests split)
|
||||||
pylint ${PYFILES}
|
pylint ${PYFILES}
|
||||||
|
no_output_timeout: 15m
|
||||||
|
|
||||||
pre-test:
|
pre-test:
|
||||||
parameters:
|
parameters:
|
||||||
@ -173,13 +182,14 @@ jobs:
|
|||||||
- install
|
- install
|
||||||
|
|
||||||
- run:
|
- run:
|
||||||
name: run tests
|
name: run tests with code coverage
|
||||||
command: |
|
command: |
|
||||||
. venv/bin/activate
|
. venv/bin/activate
|
||||||
|
CC_SWITCH="--cov --cov-report="
|
||||||
TESTFILES=$(circleci tests glob "tests/**/test_*.py" | circleci tests split --split-by=timings)
|
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 --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}
|
||||||
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}
|
|
||||||
script/check_dirty
|
script/check_dirty
|
||||||
|
codecov
|
||||||
|
|
||||||
- store_test_results:
|
- store_test_results:
|
||||||
path: test-reports
|
path: test-reports
|
||||||
|
15
.codecov.yml
Normal file
15
.codecov.yml
Normal 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
|
40
.coveragerc
40
.coveragerc
@ -21,14 +21,15 @@ omit =
|
|||||||
homeassistant/components/alarmdecoder/*
|
homeassistant/components/alarmdecoder/*
|
||||||
homeassistant/components/alarmdotcom/alarm_control_panel.py
|
homeassistant/components/alarmdotcom/alarm_control_panel.py
|
||||||
homeassistant/components/alpha_vantage/sensor.py
|
homeassistant/components/alpha_vantage/sensor.py
|
||||||
|
homeassistant/components/amazon_polly/tts.py
|
||||||
homeassistant/components/ambient_station/*
|
homeassistant/components/ambient_station/*
|
||||||
homeassistant/components/amcrest/*
|
homeassistant/components/amcrest/*
|
||||||
|
homeassistant/components/ampio/*
|
||||||
homeassistant/components/android_ip_webcam/*
|
homeassistant/components/android_ip_webcam/*
|
||||||
homeassistant/components/androidtv/*
|
homeassistant/components/androidtv/*
|
||||||
homeassistant/components/anel_pwrctrl/switch.py
|
homeassistant/components/anel_pwrctrl/switch.py
|
||||||
homeassistant/components/anthemav/media_player.py
|
homeassistant/components/anthemav/media_player.py
|
||||||
homeassistant/components/apcupsd/*
|
homeassistant/components/apcupsd/*
|
||||||
homeassistant/components/apiai/*
|
|
||||||
homeassistant/components/apple_tv/*
|
homeassistant/components/apple_tv/*
|
||||||
homeassistant/components/aqualogic/*
|
homeassistant/components/aqualogic/*
|
||||||
homeassistant/components/aquostv/media_player.py
|
homeassistant/components/aquostv/media_player.py
|
||||||
@ -45,9 +46,7 @@ omit =
|
|||||||
homeassistant/components/august/*
|
homeassistant/components/august/*
|
||||||
homeassistant/components/automatic/device_tracker.py
|
homeassistant/components/automatic/device_tracker.py
|
||||||
homeassistant/components/avion/light.py
|
homeassistant/components/avion/light.py
|
||||||
homeassistant/components/aws_lambda/notify.py
|
homeassistant/components/baidu/tts.py
|
||||||
homeassistant/components/aws_sns/notify.py
|
|
||||||
homeassistant/components/aws_sqs/notify.py
|
|
||||||
homeassistant/components/bbb_gpio/*
|
homeassistant/components/bbb_gpio/*
|
||||||
homeassistant/components/bbox/device_tracker.py
|
homeassistant/components/bbox/device_tracker.py
|
||||||
homeassistant/components/bbox/sensor.py
|
homeassistant/components/bbox/sensor.py
|
||||||
@ -64,6 +63,7 @@ omit =
|
|||||||
homeassistant/components/bme280/sensor.py
|
homeassistant/components/bme280/sensor.py
|
||||||
homeassistant/components/bme680/sensor.py
|
homeassistant/components/bme680/sensor.py
|
||||||
homeassistant/components/bmw_connected_drive/*
|
homeassistant/components/bmw_connected_drive/*
|
||||||
|
homeassistant/components/bom/camera.py
|
||||||
homeassistant/components/bom/sensor.py
|
homeassistant/components/bom/sensor.py
|
||||||
homeassistant/components/bom/weather.py
|
homeassistant/components/bom/weather.py
|
||||||
homeassistant/components/braviatv/media_player.py
|
homeassistant/components/braviatv/media_player.py
|
||||||
@ -84,6 +84,7 @@ omit =
|
|||||||
homeassistant/components/channels/media_player.py
|
homeassistant/components/channels/media_player.py
|
||||||
homeassistant/components/cisco_ios/device_tracker.py
|
homeassistant/components/cisco_ios/device_tracker.py
|
||||||
homeassistant/components/cisco_mobility_express/device_tracker.py
|
homeassistant/components/cisco_mobility_express/device_tracker.py
|
||||||
|
homeassistant/components/cisco_webex_teams/notify.py
|
||||||
homeassistant/components/ciscospark/notify.py
|
homeassistant/components/ciscospark/notify.py
|
||||||
homeassistant/components/citybikes/sensor.py
|
homeassistant/components/citybikes/sensor.py
|
||||||
homeassistant/components/clementine/media_player.py
|
homeassistant/components/clementine/media_player.py
|
||||||
@ -92,6 +93,7 @@ omit =
|
|||||||
homeassistant/components/clicksend_tts/notify.py
|
homeassistant/components/clicksend_tts/notify.py
|
||||||
homeassistant/components/cloudflare/*
|
homeassistant/components/cloudflare/*
|
||||||
homeassistant/components/cmus/media_player.py
|
homeassistant/components/cmus/media_player.py
|
||||||
|
homeassistant/components/co2signal/*
|
||||||
homeassistant/components/coinbase/*
|
homeassistant/components/coinbase/*
|
||||||
homeassistant/components/comed_hourly_pricing/sensor.py
|
homeassistant/components/comed_hourly_pricing/sensor.py
|
||||||
homeassistant/components/comfoconnect/*
|
homeassistant/components/comfoconnect/*
|
||||||
@ -125,7 +127,6 @@ omit =
|
|||||||
homeassistant/components/dlink/switch.py
|
homeassistant/components/dlink/switch.py
|
||||||
homeassistant/components/dlna_dmr/media_player.py
|
homeassistant/components/dlna_dmr/media_player.py
|
||||||
homeassistant/components/dnsip/sensor.py
|
homeassistant/components/dnsip/sensor.py
|
||||||
homeassistant/components/domain_expiry/sensor.py
|
|
||||||
homeassistant/components/dominos/*
|
homeassistant/components/dominos/*
|
||||||
homeassistant/components/doorbird/*
|
homeassistant/components/doorbird/*
|
||||||
homeassistant/components/dovado/*
|
homeassistant/components/dovado/*
|
||||||
@ -161,9 +162,12 @@ omit =
|
|||||||
homeassistant/components/envisalink/*
|
homeassistant/components/envisalink/*
|
||||||
homeassistant/components/ephember/climate.py
|
homeassistant/components/ephember/climate.py
|
||||||
homeassistant/components/epson/media_player.py
|
homeassistant/components/epson/media_player.py
|
||||||
|
homeassistant/components/epsonworkforce/sensor.py
|
||||||
homeassistant/components/eq3btsmart/climate.py
|
homeassistant/components/eq3btsmart/climate.py
|
||||||
homeassistant/components/esphome/__init__.py
|
homeassistant/components/esphome/__init__.py
|
||||||
homeassistant/components/esphome/binary_sensor.py
|
homeassistant/components/esphome/binary_sensor.py
|
||||||
|
homeassistant/components/esphome/camera.py
|
||||||
|
homeassistant/components/esphome/climate.py
|
||||||
homeassistant/components/esphome/cover.py
|
homeassistant/components/esphome/cover.py
|
||||||
homeassistant/components/esphome/fan.py
|
homeassistant/components/esphome/fan.py
|
||||||
homeassistant/components/esphome/light.py
|
homeassistant/components/esphome/light.py
|
||||||
@ -203,6 +207,7 @@ omit =
|
|||||||
homeassistant/components/futurenow/light.py
|
homeassistant/components/futurenow/light.py
|
||||||
homeassistant/components/garadget/cover.py
|
homeassistant/components/garadget/cover.py
|
||||||
homeassistant/components/gc100/*
|
homeassistant/components/gc100/*
|
||||||
|
homeassistant/components/geniushub/*
|
||||||
homeassistant/components/gearbest/sensor.py
|
homeassistant/components/gearbest/sensor.py
|
||||||
homeassistant/components/geizhals/sensor.py
|
homeassistant/components/geizhals/sensor.py
|
||||||
homeassistant/components/github/sensor.py
|
homeassistant/components/github/sensor.py
|
||||||
@ -266,13 +271,10 @@ omit =
|
|||||||
homeassistant/components/ifttt/*
|
homeassistant/components/ifttt/*
|
||||||
homeassistant/components/iglo/light.py
|
homeassistant/components/iglo/light.py
|
||||||
homeassistant/components/ihc/*
|
homeassistant/components/ihc/*
|
||||||
homeassistant/components/iliad_italy/sensor.py
|
|
||||||
homeassistant/components/imap/sensor.py
|
homeassistant/components/imap/sensor.py
|
||||||
homeassistant/components/imap_email_content/sensor.py
|
homeassistant/components/imap_email_content/sensor.py
|
||||||
homeassistant/components/influxdb/sensor.py
|
homeassistant/components/influxdb/sensor.py
|
||||||
homeassistant/components/insteon/*
|
homeassistant/components/insteon/*
|
||||||
homeassistant/components/insteon_local/*
|
|
||||||
homeassistant/components/insteon_plm/*
|
|
||||||
homeassistant/components/ios/*
|
homeassistant/components/ios/*
|
||||||
homeassistant/components/iota/*
|
homeassistant/components/iota/*
|
||||||
homeassistant/components/iperf3/*
|
homeassistant/components/iperf3/*
|
||||||
@ -318,7 +320,10 @@ omit =
|
|||||||
homeassistant/components/liveboxplaytv/media_player.py
|
homeassistant/components/liveboxplaytv/media_player.py
|
||||||
homeassistant/components/llamalab_automate/notify.py
|
homeassistant/components/llamalab_automate/notify.py
|
||||||
homeassistant/components/lockitron/lock.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/london_underground/sensor.py
|
||||||
homeassistant/components/loopenergy/sensor.py
|
homeassistant/components/loopenergy/sensor.py
|
||||||
homeassistant/components/luci/device_tracker.py
|
homeassistant/components/luci/device_tracker.py
|
||||||
@ -341,6 +346,7 @@ omit =
|
|||||||
homeassistant/components/meteo_france/*
|
homeassistant/components/meteo_france/*
|
||||||
homeassistant/components/metoffice/sensor.py
|
homeassistant/components/metoffice/sensor.py
|
||||||
homeassistant/components/metoffice/weather.py
|
homeassistant/components/metoffice/weather.py
|
||||||
|
homeassistant/components/microsoft/tts.py
|
||||||
homeassistant/components/miflora/sensor.py
|
homeassistant/components/miflora/sensor.py
|
||||||
homeassistant/components/mikrotik/device_tracker.py
|
homeassistant/components/mikrotik/device_tracker.py
|
||||||
homeassistant/components/mill/climate.py
|
homeassistant/components/mill/climate.py
|
||||||
@ -363,8 +369,8 @@ omit =
|
|||||||
homeassistant/components/mystrom/binary_sensor.py
|
homeassistant/components/mystrom/binary_sensor.py
|
||||||
homeassistant/components/mystrom/light.py
|
homeassistant/components/mystrom/light.py
|
||||||
homeassistant/components/mystrom/switch.py
|
homeassistant/components/mystrom/switch.py
|
||||||
|
homeassistant/components/n26/*
|
||||||
homeassistant/components/nad/media_player.py
|
homeassistant/components/nad/media_player.py
|
||||||
homeassistant/components/nadtcp/media_player.py
|
|
||||||
homeassistant/components/nanoleaf/light.py
|
homeassistant/components/nanoleaf/light.py
|
||||||
homeassistant/components/neato/*
|
homeassistant/components/neato/*
|
||||||
homeassistant/components/nederlandse_spoorwegen/sensor.py
|
homeassistant/components/nederlandse_spoorwegen/sensor.py
|
||||||
@ -373,7 +379,6 @@ omit =
|
|||||||
homeassistant/components/netatmo/*
|
homeassistant/components/netatmo/*
|
||||||
homeassistant/components/netatmo_public/sensor.py
|
homeassistant/components/netatmo_public/sensor.py
|
||||||
homeassistant/components/netdata/sensor.py
|
homeassistant/components/netdata/sensor.py
|
||||||
homeassistant/components/netdata_public/sensor.py
|
|
||||||
homeassistant/components/netgear/device_tracker.py
|
homeassistant/components/netgear/device_tracker.py
|
||||||
homeassistant/components/netgear_lte/*
|
homeassistant/components/netgear_lte/*
|
||||||
homeassistant/components/netio/switch.py
|
homeassistant/components/netio/switch.py
|
||||||
@ -394,6 +399,7 @@ omit =
|
|||||||
homeassistant/components/nzbget/sensor.py
|
homeassistant/components/nzbget/sensor.py
|
||||||
homeassistant/components/octoprint/*
|
homeassistant/components/octoprint/*
|
||||||
homeassistant/components/oem/climate.py
|
homeassistant/components/oem/climate.py
|
||||||
|
homeassistant/components/oasa_telematics/sensor.py
|
||||||
homeassistant/components/ohmconnect/sensor.py
|
homeassistant/components/ohmconnect/sensor.py
|
||||||
homeassistant/components/onewire/sensor.py
|
homeassistant/components/onewire/sensor.py
|
||||||
homeassistant/components/onkyo/media_player.py
|
homeassistant/components/onkyo/media_player.py
|
||||||
@ -422,6 +428,7 @@ omit =
|
|||||||
homeassistant/components/pencom/switch.py
|
homeassistant/components/pencom/switch.py
|
||||||
homeassistant/components/philips_js/media_player.py
|
homeassistant/components/philips_js/media_player.py
|
||||||
homeassistant/components/pi_hole/sensor.py
|
homeassistant/components/pi_hole/sensor.py
|
||||||
|
homeassistant/components/picotts/tts.py
|
||||||
homeassistant/components/piglow/light.py
|
homeassistant/components/piglow/light.py
|
||||||
homeassistant/components/pilight/*
|
homeassistant/components/pilight/*
|
||||||
homeassistant/components/ping/binary_sensor.py
|
homeassistant/components/ping/binary_sensor.py
|
||||||
@ -533,6 +540,7 @@ omit =
|
|||||||
homeassistant/components/sochain/sensor.py
|
homeassistant/components/sochain/sensor.py
|
||||||
homeassistant/components/socialblade/sensor.py
|
homeassistant/components/socialblade/sensor.py
|
||||||
homeassistant/components/solaredge/sensor.py
|
homeassistant/components/solaredge/sensor.py
|
||||||
|
homeassistant/components/somfy_mylink/*
|
||||||
homeassistant/components/sonarr/sensor.py
|
homeassistant/components/sonarr/sensor.py
|
||||||
homeassistant/components/songpal/media_player.py
|
homeassistant/components/songpal/media_player.py
|
||||||
homeassistant/components/sonos/*
|
homeassistant/components/sonos/*
|
||||||
@ -546,6 +554,7 @@ omit =
|
|||||||
homeassistant/components/srp_energy/sensor.py
|
homeassistant/components/srp_energy/sensor.py
|
||||||
homeassistant/components/starlingbank/sensor.py
|
homeassistant/components/starlingbank/sensor.py
|
||||||
homeassistant/components/steam_online/sensor.py
|
homeassistant/components/steam_online/sensor.py
|
||||||
|
homeassistant/components/stiebel_eltron/*
|
||||||
homeassistant/components/stride/notify.py
|
homeassistant/components/stride/notify.py
|
||||||
homeassistant/components/supervisord/sensor.py
|
homeassistant/components/supervisord/sensor.py
|
||||||
homeassistant/components/swiss_hydrological_data/sensor.py
|
homeassistant/components/swiss_hydrological_data/sensor.py
|
||||||
@ -573,7 +582,6 @@ omit =
|
|||||||
homeassistant/components/tellduslive/*
|
homeassistant/components/tellduslive/*
|
||||||
homeassistant/components/tellstick/*
|
homeassistant/components/tellstick/*
|
||||||
homeassistant/components/telnet/switch.py
|
homeassistant/components/telnet/switch.py
|
||||||
homeassistant/components/telstra/notify.py
|
|
||||||
homeassistant/components/temper/sensor.py
|
homeassistant/components/temper/sensor.py
|
||||||
homeassistant/components/tensorflow/image_processing.py
|
homeassistant/components/tensorflow/image_processing.py
|
||||||
homeassistant/components/tesla/*
|
homeassistant/components/tesla/*
|
||||||
@ -605,10 +613,6 @@ omit =
|
|||||||
homeassistant/components/trafikverket_weatherstation/sensor.py
|
homeassistant/components/trafikverket_weatherstation/sensor.py
|
||||||
homeassistant/components/transmission/*
|
homeassistant/components/transmission/*
|
||||||
homeassistant/components/travisci/sensor.py
|
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/tuya/*
|
||||||
homeassistant/components/twilio_call/notify.py
|
homeassistant/components/twilio_call/notify.py
|
||||||
homeassistant/components/twilio_sms/notify.py
|
homeassistant/components/twilio_sms/notify.py
|
||||||
@ -650,6 +654,7 @@ omit =
|
|||||||
homeassistant/components/wirelesstag/*
|
homeassistant/components/wirelesstag/*
|
||||||
homeassistant/components/worldtidesinfo/sensor.py
|
homeassistant/components/worldtidesinfo/sensor.py
|
||||||
homeassistant/components/worxlandroid/sensor.py
|
homeassistant/components/worxlandroid/sensor.py
|
||||||
|
homeassistant/components/wunderlist/*
|
||||||
homeassistant/components/x10/light.py
|
homeassistant/components/x10/light.py
|
||||||
homeassistant/components/xbox_live/sensor.py
|
homeassistant/components/xbox_live/sensor.py
|
||||||
homeassistant/components/xeoma/camera.py
|
homeassistant/components/xeoma/camera.py
|
||||||
@ -663,7 +668,7 @@ omit =
|
|||||||
homeassistant/components/yale_smart_alarm/alarm_control_panel.py
|
homeassistant/components/yale_smart_alarm/alarm_control_panel.py
|
||||||
homeassistant/components/yamaha/media_player.py
|
homeassistant/components/yamaha/media_player.py
|
||||||
homeassistant/components/yamaha_musiccast/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/yeelightsunflower/light.py
|
||||||
homeassistant/components/yi/camera.py
|
homeassistant/components/yi/camera.py
|
||||||
homeassistant/components/zabbix/*
|
homeassistant/components/zabbix/*
|
||||||
@ -688,6 +693,7 @@ omit =
|
|||||||
homeassistant/components/zigbee/*
|
homeassistant/components/zigbee/*
|
||||||
homeassistant/components/ziggo_mediabox_xl/media_player.py
|
homeassistant/components/ziggo_mediabox_xl/media_player.py
|
||||||
homeassistant/components/zoneminder/*
|
homeassistant/components/zoneminder/*
|
||||||
|
homeassistant/components/supla/*
|
||||||
homeassistant/components/zwave/util.py
|
homeassistant/components/zwave/util.py
|
||||||
|
|
||||||
[report]
|
[report]
|
||||||
|
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
7
.github/PULL_REQUEST_TEMPLATE.md
vendored
@ -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)
|
- [ ] 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:
|
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 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 or updated dependencies have been added to `requirements_all.txt` by running `script/gen_requirements_all.py`.
|
||||||
- [ ] New files were added to `.coveragerc`.
|
- [ ] 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:
|
If the code does not interact with devices:
|
||||||
- [ ] Tests have been added to verify that the new code works.
|
- [ ] 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
|
[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
45
.github/main.workflow
vendored
@ -1,41 +1,14 @@
|
|||||||
workflow "Python 3.7 - tox" {
|
workflow "Mention CODEOWNERS of integrations when integration label is added to an issue" {
|
||||||
resolves = ["Python 3.7 - tests"]
|
on = "issues"
|
||||||
on = "push"
|
resolves = "codeowners-mention"
|
||||||
}
|
}
|
||||||
|
|
||||||
action "Python 3.7 - tests" {
|
workflow "Mention CODEOWNERS of integrations when integration label is added to an PRs" {
|
||||||
uses = "home-assistant/actions/py37-tox@master"
|
on = "pull_request"
|
||||||
args = "-e py37"
|
resolves = "codeowners-mention"
|
||||||
}
|
}
|
||||||
|
|
||||||
workflow "Python 3.6 - tox" {
|
action "codeowners-mention" {
|
||||||
resolves = ["Python 3.6 - tests"]
|
uses = "home-assistant/codeowners-mention@master"
|
||||||
on = "push"
|
secrets = ["GITHUB_TOKEN"]
|
||||||
}
|
|
||||||
|
|
||||||
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"]
|
|
||||||
}
|
}
|
||||||
|
55
.travis.yml
55
.travis.yml
@ -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
|
|
367
CODEOWNERS
367
CODEOWNERS
@ -1,3 +1,4 @@
|
|||||||
|
# This file is generated by script/manifest/codeowners.py
|
||||||
# People marked here will be automatically requested for a review
|
# People marked here will be automatically requested for a review
|
||||||
# when the code that they own is touched.
|
# when the code that they own is touched.
|
||||||
# https://github.com/blog/2392-introducing-code-owners
|
# https://github.com/blog/2392-introducing-code-owners
|
||||||
@ -7,285 +8,255 @@ setup.py @home-assistant/core
|
|||||||
homeassistant/*.py @home-assistant/core
|
homeassistant/*.py @home-assistant/core
|
||||||
homeassistant/helpers/* @home-assistant/core
|
homeassistant/helpers/* @home-assistant/core
|
||||||
homeassistant/util/* @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
|
Dockerfile @home-assistant/docker
|
||||||
virtualization/Docker/* @home-assistant/docker
|
virtualization/Docker/* @home-assistant/docker
|
||||||
|
|
||||||
homeassistant/components/zwave/* @home-assistant/z-wave
|
# Other code
|
||||||
homeassistant/components/*/zwave.py @home-assistant/z-wave
|
homeassistant/scripts/check_config.py @kellerza
|
||||||
|
|
||||||
homeassistant/components/hassio/* @home-assistant/hassio
|
# Integrations
|
||||||
|
homeassistant/components/airvisual/* @bachya
|
||||||
# Individual platforms
|
homeassistant/components/alarm_control_panel/* @colinodell
|
||||||
homeassistant/components/notify/aws_lambda.py @robbiet480
|
homeassistant/components/alpha_vantage/* @fabaff
|
||||||
homeassistant/components/notify/aws_sns.py @robbiet480
|
homeassistant/components/amazon_polly/* @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
|
|
||||||
homeassistant/components/ambient_station/* @bachya
|
homeassistant/components/ambient_station/* @bachya
|
||||||
|
homeassistant/components/api/* @home-assistant/core
|
||||||
homeassistant/components/arduino/* @fabaff
|
homeassistant/components/arduino/* @fabaff
|
||||||
homeassistant/components/arest/* @fabaff
|
homeassistant/components/arest/* @fabaff
|
||||||
homeassistant/components/asuswrt/device_tracker.py @kennedyshead
|
homeassistant/components/asuswrt/* @kennedyshead
|
||||||
homeassistant/components/automatic/device_tracker.py @armills
|
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
|
homeassistant/components/axis/* @kane610
|
||||||
|
homeassistant/components/bitcoin/* @fabaff
|
||||||
# B
|
|
||||||
homeassistant/components/bitcoin/sensor.py @fabaff
|
|
||||||
homeassistant/components/blink/* @fronzbot
|
homeassistant/components/blink/* @fronzbot
|
||||||
homeassistant/components/bmw_connected_drive/* @ChristianKuehnel
|
homeassistant/components/bmw_connected_drive/* @ChristianKuehnel
|
||||||
homeassistant/components/braviatv/media_player.py @robbiet480
|
homeassistant/components/braviatv/* @robbiet480
|
||||||
homeassistant/components/broadlink/* @danielhiversen
|
homeassistant/components/broadlink/* @danielhiversen
|
||||||
homeassistant/components/brunt/cover.py @eavanvalkenburg
|
homeassistant/components/brunt/* @eavanvalkenburg
|
||||||
homeassistant/components/bt_smarthub/device_tracker.py @jxwolstenholme
|
homeassistant/components/bt_smarthub/* @jxwolstenholme
|
||||||
|
homeassistant/components/cisco_ios/* @fbradyirl
|
||||||
# C
|
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/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/counter/* @fabaff
|
||||||
homeassistant/components/cover/group.py @cdce8p
|
homeassistant/components/cover/* @home-assistant/core
|
||||||
homeassistant/components/cpuspeed/sensor.py @fabaff
|
homeassistant/components/cpuspeed/* @fabaff
|
||||||
homeassistant/components/cups/sensor.py @fabaff
|
homeassistant/components/cups/* @fabaff
|
||||||
|
|
||||||
# D
|
|
||||||
homeassistant/components/daikin/* @fredrike @rofrantz
|
homeassistant/components/daikin/* @fredrike @rofrantz
|
||||||
homeassistant/components/darksky/* @fabaff
|
homeassistant/components/darksky/* @fabaff
|
||||||
homeassistant/components/discogs/sensor.py @thibmaek
|
|
||||||
homeassistant/components/deconz/* @kane610
|
homeassistant/components/deconz/* @kane610
|
||||||
homeassistant/components/demo/weather.py @fabaff
|
homeassistant/components/demo/* @home-assistant/core
|
||||||
homeassistant/components/digital_ocean/* @fabaff
|
homeassistant/components/digital_ocean/* @fabaff
|
||||||
|
homeassistant/components/discogs/* @thibmaek
|
||||||
homeassistant/components/doorbird/* @oblogic7
|
homeassistant/components/doorbird/* @oblogic7
|
||||||
homeassistant/components/dweet/* @fabaff
|
homeassistant/components/dweet/* @fabaff
|
||||||
|
|
||||||
# E
|
|
||||||
homeassistant/components/ecovacs/* @OverloadUT
|
homeassistant/components/ecovacs/* @OverloadUT
|
||||||
homeassistant/components/edp_redy/* @abmantis
|
homeassistant/components/edp_redy/* @abmantis
|
||||||
homeassistant/components/eight_sleep/* @mezz64
|
|
||||||
homeassistant/components/egardia/* @jeroenterheerdt
|
homeassistant/components/egardia/* @jeroenterheerdt
|
||||||
homeassistant/components/emby/media_player.py @mezz64
|
homeassistant/components/eight_sleep/* @mezz64
|
||||||
homeassistant/components/ephember/climate.py @ttroy50
|
homeassistant/components/emby/* @mezz64
|
||||||
homeassistant/components/eq3btsmart/climate.py @rytilahti
|
homeassistant/components/enigma2/* @fbradyirl
|
||||||
|
homeassistant/components/ephember/* @ttroy50
|
||||||
|
homeassistant/components/epsonworkforce/* @ThaStealth
|
||||||
|
homeassistant/components/eq3btsmart/* @rytilahti
|
||||||
homeassistant/components/esphome/* @OttoWinter
|
homeassistant/components/esphome/* @OttoWinter
|
||||||
|
homeassistant/components/file/* @fabaff
|
||||||
# F
|
homeassistant/components/filter/* @dgomes
|
||||||
homeassistant/components/file/sensor.py @fabaff
|
homeassistant/components/fitbit/* @robbiet480
|
||||||
homeassistant/components/filter/sensor.py @dgomes
|
homeassistant/components/fixer/* @fabaff
|
||||||
homeassistant/components/fitbit/sensor.py @robbiet480
|
homeassistant/components/flock/* @fabaff
|
||||||
homeassistant/components/fixer/sensor.py @fabaff
|
homeassistant/components/flunearyou/* @bachya
|
||||||
homeassistant/components/flunearyou/sensor.py @bachya
|
|
||||||
homeassistant/components/foursquare/* @robbiet480
|
homeassistant/components/foursquare/* @robbiet480
|
||||||
homeassistant/components/freebox/* @snoof85
|
homeassistant/components/freebox/* @snoof85
|
||||||
|
homeassistant/components/frontend/* @home-assistant/core
|
||||||
# G
|
homeassistant/components/gearbest/* @HerrHofrat
|
||||||
homeassistant/components/gearbest/sensor.py @HerrHofrat
|
homeassistant/components/gitter/* @fabaff
|
||||||
homeassistant/components/gitter/sensor.py @fabaff
|
homeassistant/components/glances/* @fabaff
|
||||||
homeassistant/components/glances/sensor.py @fabaff
|
homeassistant/components/gntp/* @robbiet480
|
||||||
homeassistant/components/google_travel_time/sensor.py @robbiet480
|
homeassistant/components/google_translate/* @awarecan
|
||||||
|
homeassistant/components/google_travel_time/* @robbiet480
|
||||||
homeassistant/components/googlehome/* @ludeeus
|
homeassistant/components/googlehome/* @ludeeus
|
||||||
homeassistant/components/gpsd/sensor.py @fabaff
|
homeassistant/components/gpsd/* @fabaff
|
||||||
homeassistant/components/gtfs/sensor.py @robbiet480
|
homeassistant/components/group/* @home-assistant/core
|
||||||
|
homeassistant/components/gtfs/* @robbiet480
|
||||||
# H
|
|
||||||
homeassistant/components/harmony/* @ehendrix23
|
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/history_graph/* @andrey-git
|
||||||
homeassistant/components/hive/* @Rendili @KJonline
|
homeassistant/components/hive/* @Rendili @KJonline
|
||||||
|
homeassistant/components/homeassistant/* @home-assistant/core
|
||||||
homeassistant/components/homekit/* @cdce8p
|
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_lte/* @scop
|
||||||
homeassistant/components/huawei_router/device_tracker.py @abmantis
|
homeassistant/components/huawei_router/* @abmantis
|
||||||
|
homeassistant/components/hue/* @balloob
|
||||||
# I
|
homeassistant/components/ign_sismologia/* @exxamalte
|
||||||
homeassistant/components/influxdb/* @fabaff
|
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/ios/* @robbiet480
|
||||||
homeassistant/components/ipma/* @dgomes
|
homeassistant/components/ipma/* @dgomes
|
||||||
homeassistant/components/irish_rail_transport/sensor.py @ttroy50
|
homeassistant/components/irish_rail_transport/* @ttroy50
|
||||||
|
homeassistant/components/jewish_calendar/* @tsvi
|
||||||
# J
|
|
||||||
homeassistant/components/jewish_calendar/sensor.py @tsvi
|
|
||||||
|
|
||||||
# K
|
|
||||||
homeassistant/components/knx/* @Julius2342
|
homeassistant/components/knx/* @Julius2342
|
||||||
homeassistant/components/kodi/media_player.py @armills
|
homeassistant/components/kodi/* @armills
|
||||||
homeassistant/components/konnected/* @heythisisnate
|
homeassistant/components/konnected/* @heythisisnate
|
||||||
|
homeassistant/components/lametric/* @robbiet480
|
||||||
# L
|
homeassistant/components/launch_library/* @ludeeus
|
||||||
homeassistant/components/lametric/notify.py @robbiet480
|
|
||||||
homeassistant/components/launch_library/sensor.py @ludeeus
|
|
||||||
homeassistant/components/lifx/* @amelchio
|
homeassistant/components/lifx/* @amelchio
|
||||||
homeassistant/components/lifx_cloud/scene.py @amelchio
|
homeassistant/components/lifx_cloud/* @amelchio
|
||||||
homeassistant/components/lifx_legacy/light.py @amelchio
|
homeassistant/components/lifx_legacy/* @amelchio
|
||||||
homeassistant/components/linux_battery/sensor.py @fabaff
|
homeassistant/components/linux_battery/* @fabaff
|
||||||
homeassistant/components/liveboxplaytv/media_player.py @pschmitt
|
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
|
homeassistant/components/luftdaten/* @fabaff
|
||||||
|
homeassistant/components/mastodon/* @fabaff
|
||||||
# M
|
|
||||||
homeassistant/components/matrix/* @tinloaf
|
homeassistant/components/matrix/* @tinloaf
|
||||||
homeassistant/components/mediaroom/media_player.py @dgomes
|
homeassistant/components/mediaroom/* @dgomes
|
||||||
homeassistant/components/melissa/* @kennedyshead
|
homeassistant/components/melissa/* @kennedyshead
|
||||||
homeassistant/components/met/weather.py @danielhiversen
|
homeassistant/components/met/* @danielhiversen
|
||||||
homeassistant/components/miflora/sensor.py @danielhiversen @ChristianKuehnel
|
homeassistant/components/miflora/* @danielhiversen @ChristianKuehnel
|
||||||
homeassistant/components/mill/climate.py @danielhiversen
|
homeassistant/components/mill/* @danielhiversen
|
||||||
homeassistant/components/min_max/sensor.py @fabaff
|
homeassistant/components/min_max/* @fabaff
|
||||||
homeassistant/components/mobile_app/* @robbiet480
|
homeassistant/components/mobile_app/* @robbiet480
|
||||||
homeassistant/components/monoprice/media_player.py @etsinko
|
homeassistant/components/monoprice/* @etsinko
|
||||||
homeassistant/components/moon/sensor.py @fabaff
|
homeassistant/components/moon/* @fabaff
|
||||||
homeassistant/components/mpd/media_player.py @fabaff
|
homeassistant/components/mpd/* @fabaff
|
||||||
|
homeassistant/components/mqtt/* @home-assistant/core
|
||||||
homeassistant/components/mystrom/* @fabaff
|
homeassistant/components/mystrom/* @fabaff
|
||||||
|
homeassistant/components/nello/* @pschmitt
|
||||||
# N
|
|
||||||
homeassistant/components/nello/lock.py @pschmitt
|
|
||||||
homeassistant/components/ness_alarm/* @nickw444
|
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/nissan_leaf/* @filcole
|
||||||
homeassistant/components/nmbs/sensor.py @thibmaek
|
homeassistant/components/nmbs/* @thibmaek
|
||||||
homeassistant/components/no_ip/* @fabaff
|
homeassistant/components/no_ip/* @fabaff
|
||||||
homeassistant/components/nuki/lock.py @pschmitt
|
homeassistant/components/notify/* @flowolf
|
||||||
homeassistant/components/nsw_fuel_station/sensor.py @nickw444
|
homeassistant/components/nsw_fuel_station/* @nickw444
|
||||||
|
homeassistant/components/nuki/* @pschmitt
|
||||||
# O
|
homeassistant/components/ohmconnect/* @robbiet480
|
||||||
homeassistant/components/ohmconnect/sensor.py @robbiet480
|
homeassistant/components/onboarding/* @home-assistant/core
|
||||||
homeassistant/components/openuv/* @bachya
|
homeassistant/components/openuv/* @bachya
|
||||||
homeassistant/components/openweathermap/weather.py @fabaff
|
homeassistant/components/openweathermap/* @fabaff
|
||||||
homeassistant/components/owlet/* @oblogic7
|
homeassistant/components/owlet/* @oblogic7
|
||||||
|
homeassistant/components/panel_custom/* @home-assistant/core
|
||||||
# P
|
homeassistant/components/panel_iframe/* @home-assistant/core
|
||||||
homeassistant/components/pi_hole/sensor.py @fabaff
|
homeassistant/components/persistent_notification/* @home-assistant/core
|
||||||
|
homeassistant/components/pi_hole/* @fabaff
|
||||||
homeassistant/components/plant/* @ChristianKuehnel
|
homeassistant/components/plant/* @ChristianKuehnel
|
||||||
homeassistant/components/point/* @fredrike
|
homeassistant/components/point/* @fredrike
|
||||||
homeassistant/components/pollen/sensor.py @bachya
|
homeassistant/components/pollen/* @bachya
|
||||||
homeassistant/components/push/camera.py @dgomes
|
homeassistant/components/push/* @dgomes
|
||||||
homeassistant/components/pvoutput/sensor.py @fabaff
|
homeassistant/components/pvoutput/* @fabaff
|
||||||
|
homeassistant/components/qnap/* @colinodell
|
||||||
# Q
|
homeassistant/components/quantum_gateway/* @cisasteelersfan
|
||||||
homeassistant/components/qnap/sensor.py @colinodell
|
|
||||||
homeassistant/components/quantum_gateway/device_tracker.py @cisasteelersfan
|
|
||||||
homeassistant/components/qwikswitch/* @kellerza
|
homeassistant/components/qwikswitch/* @kellerza
|
||||||
|
homeassistant/components/raincloud/* @vanstinator
|
||||||
# R
|
|
||||||
homeassistant/components/rainmachine/* @bachya
|
homeassistant/components/rainmachine/* @bachya
|
||||||
homeassistant/components/random/* @fabaff
|
homeassistant/components/random/* @fabaff
|
||||||
homeassistant/components/rfxtrx/* @danielhiversen
|
homeassistant/components/rfxtrx/* @danielhiversen
|
||||||
homeassistant/components/rmvtransport/* @cgtobi
|
homeassistant/components/rmvtransport/* @cgtobi
|
||||||
homeassistant/components/roomba/vacuum.py @pschmitt
|
homeassistant/components/roomba/* @pschmitt
|
||||||
homeassistant/components/ruter/sensor.py @ludeeus
|
homeassistant/components/ruter/* @ludeeus
|
||||||
|
homeassistant/components/scene/* @home-assistant/core
|
||||||
# S
|
homeassistant/components/scrape/* @fabaff
|
||||||
homeassistant/components/scrape/sensor.py @fabaff
|
homeassistant/components/script/* @home-assistant/core
|
||||||
homeassistant/components/sensibo/climate.py @andrey-git
|
homeassistant/components/sensibo/* @andrey-git
|
||||||
homeassistant/components/serial/sensor.py @fabaff
|
homeassistant/components/serial/* @fabaff
|
||||||
homeassistant/components/seventeentrack/sensor.py @bachya
|
homeassistant/components/seventeentrack/* @bachya
|
||||||
|
homeassistant/components/shell_command/* @home-assistant/core
|
||||||
homeassistant/components/shiftr/* @fabaff
|
homeassistant/components/shiftr/* @fabaff
|
||||||
homeassistant/components/shodan/sensor.py @fabaff
|
homeassistant/components/shodan/* @fabaff
|
||||||
homeassistant/components/simplisafe/* @bachya
|
homeassistant/components/simplisafe/* @bachya
|
||||||
homeassistant/components/sma/sensor.py @kellerza
|
homeassistant/components/sma/* @kellerza
|
||||||
homeassistant/components/smartthings/* @andrewsayre
|
homeassistant/components/smartthings/* @andrewsayre
|
||||||
|
homeassistant/components/smtp/* @fabaff
|
||||||
homeassistant/components/sonos/* @amelchio
|
homeassistant/components/sonos/* @amelchio
|
||||||
homeassistant/components/spaceapi/* @fabaff
|
homeassistant/components/spaceapi/* @fabaff
|
||||||
homeassistant/components/spider/* @peternijssen
|
homeassistant/components/spider/* @peternijssen
|
||||||
homeassistant/components/sql/sensor.py @dgomes
|
homeassistant/components/sql/* @dgomes
|
||||||
homeassistant/components/statistics/sensor.py @fabaff
|
homeassistant/components/statistics/* @fabaff
|
||||||
homeassistant/components/swiss_*/* @fabaff
|
homeassistant/components/stiebel_eltron/* @fucm
|
||||||
homeassistant/components/switchbot/switch.py @danielhiversen
|
homeassistant/components/sun/* @home-assistant/core
|
||||||
homeassistant/components/switchmate/switch.py @danielhiversen
|
homeassistant/components/supla/* @mwegrzynek
|
||||||
homeassistant/components/synology_srm/device_tracker.py @aerialls
|
homeassistant/components/swiss_hydrological_data/* @fabaff
|
||||||
homeassistant/components/sytadin/sensor.py @gautric
|
homeassistant/components/swiss_public_transport/* @fabaff
|
||||||
|
homeassistant/components/switchbot/* @danielhiversen
|
||||||
# T
|
homeassistant/components/switchmate/* @danielhiversen
|
||||||
|
homeassistant/components/synology_srm/* @aerialls
|
||||||
|
homeassistant/components/syslog/* @fabaff
|
||||||
|
homeassistant/components/sytadin/* @gautric
|
||||||
homeassistant/components/tahoma/* @philklei
|
homeassistant/components/tahoma/* @philklei
|
||||||
homeassistant/components/tautulli/sensor.py @ludeeus
|
homeassistant/components/tautulli/* @ludeeus
|
||||||
homeassistant/components/tellduslive/* @fredrike
|
homeassistant/components/tellduslive/* @fredrike
|
||||||
homeassistant/components/template/cover.py @PhracturedBlue
|
homeassistant/components/template/* @PhracturedBlue
|
||||||
homeassistant/components/tesla/* @zabuldon
|
homeassistant/components/tesla/* @zabuldon
|
||||||
homeassistant/components/tfiac/* @fredrike @mellado
|
homeassistant/components/tfiac/* @fredrike @mellado
|
||||||
homeassistant/components/thethingsnetwork/* @fabaff
|
homeassistant/components/thethingsnetwork/* @fabaff
|
||||||
homeassistant/components/threshold/binary_sensor.py @fabaff
|
homeassistant/components/threshold/* @fabaff
|
||||||
homeassistant/components/tibber/* @danielhiversen
|
homeassistant/components/tibber/* @danielhiversen
|
||||||
homeassistant/components/tile/device_tracker.py @bachya
|
homeassistant/components/tile/* @bachya
|
||||||
homeassistant/components/time_date/sensor.py @fabaff
|
homeassistant/components/time_date/* @fabaff
|
||||||
homeassistant/components/toon/* @frenck
|
homeassistant/components/toon/* @frenck
|
||||||
homeassistant/components/tplink/* @rytilahti
|
homeassistant/components/tplink/* @rytilahti
|
||||||
homeassistant/components/traccar/device_tracker.py @ludeeus
|
homeassistant/components/traccar/* @ludeeus
|
||||||
homeassistant/components/tradfri/* @ggravlingen
|
homeassistant/components/tradfri/* @ggravlingen
|
||||||
|
homeassistant/components/tts/* @robbiet480
|
||||||
# U
|
homeassistant/components/twilio_call/* @robbiet480
|
||||||
homeassistant/components/uber/sensor.py @robbiet480
|
homeassistant/components/twilio_sms/* @robbiet480
|
||||||
|
homeassistant/components/uber/* @robbiet480
|
||||||
homeassistant/components/unifi/* @kane610
|
homeassistant/components/unifi/* @kane610
|
||||||
homeassistant/components/upcloud/* @scop
|
homeassistant/components/upcloud/* @scop
|
||||||
|
homeassistant/components/updater/* @home-assistant/core
|
||||||
homeassistant/components/upnp/* @robbiet480
|
homeassistant/components/upnp/* @robbiet480
|
||||||
homeassistant/components/uptimerobot/binary_sensor.py @ludeeus
|
homeassistant/components/uptimerobot/* @ludeeus
|
||||||
homeassistant/components/utility_meter/* @dgomes
|
homeassistant/components/utility_meter/* @dgomes
|
||||||
|
|
||||||
# V
|
|
||||||
homeassistant/components/velux/* @Julius2342
|
homeassistant/components/velux/* @Julius2342
|
||||||
homeassistant/components/version/sensor.py @fabaff
|
homeassistant/components/version/* @fabaff
|
||||||
|
homeassistant/components/waqi/* @andrey-git
|
||||||
# W
|
homeassistant/components/weather/* @fabaff
|
||||||
homeassistant/components/waqi/sensor.py @andrey-git
|
homeassistant/components/weblink/* @home-assistant/core
|
||||||
homeassistant/components/weather/__init__.py @fabaff
|
homeassistant/components/websocket_api/* @home-assistant/core
|
||||||
homeassistant/components/wemo/* @sqldiablo
|
homeassistant/components/wemo/* @sqldiablo
|
||||||
homeassistant/components/worldclock/sensor.py @fabaff
|
homeassistant/components/worldclock/* @fabaff
|
||||||
|
homeassistant/components/xfinity/* @cisasteelersfan
|
||||||
# X
|
|
||||||
homeassistant/components/xfinity/device_tracker.py @cisasteelersfan
|
|
||||||
homeassistant/components/xiaomi_aqara/* @danielhiversen @syssi
|
homeassistant/components/xiaomi_aqara/* @danielhiversen @syssi
|
||||||
homeassistant/components/xiaomi_miio/* @rytilahti @syssi
|
homeassistant/components/xiaomi_miio/* @rytilahti @syssi
|
||||||
homeassistant/components/xiaomi_tv/media_player.py @fattdev
|
homeassistant/components/xiaomi_tv/* @fattdev
|
||||||
|
homeassistant/components/xmpp/* @fabaff
|
||||||
# Y
|
|
||||||
homeassistant/components/yamaha_musiccast/* @jalmeroth
|
homeassistant/components/yamaha_musiccast/* @jalmeroth
|
||||||
homeassistant/components/yeelight/* @rytilahti @zewelor
|
homeassistant/components/yeelight/* @rytilahti @zewelor
|
||||||
homeassistant/components/yeelightsunflower/light.py @lindsaymarkward
|
homeassistant/components/yeelightsunflower/* @lindsaymarkward
|
||||||
homeassistant/components/yi/camera.py @bachya
|
homeassistant/components/yessssms/* @flowolf
|
||||||
|
homeassistant/components/yi/* @bachya
|
||||||
# Z
|
|
||||||
homeassistant/components/zeroconf/* @robbiet480
|
homeassistant/components/zeroconf/* @robbiet480
|
||||||
homeassistant/components/zha/* @dmulcahey @adminiuga
|
homeassistant/components/zha/* @dmulcahey @adminiuga
|
||||||
|
homeassistant/components/zone/* @home-assistant/core
|
||||||
homeassistant/components/zoneminder/* @rohankapoorcom
|
homeassistant/components/zoneminder/* @rohankapoorcom
|
||||||
|
homeassistant/components/zwave/* @home-assistant/z-wave
|
||||||
|
|
||||||
# Other code
|
# Individual files
|
||||||
homeassistant/scripts/check_config.py @kellerza
|
homeassistant/components/group/cover @cdce8p
|
||||||
|
homeassistant/components/demo/weather @fabaff
|
||||||
|
@ -27,7 +27,7 @@ COPY requirements_all.txt requirements_all.txt
|
|||||||
# Uninstall enum34 because some dependencies install it but breaks Python 3.4+.
|
# Uninstall enum34 because some dependencies install it but breaks Python 3.4+.
|
||||||
# See PR #8103 for more info.
|
# See PR #8103 for more info.
|
||||||
RUN pip3 install --no-cache-dir -r requirements_all.txt && \
|
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 source
|
||||||
COPY . .
|
COPY . .
|
||||||
|
@ -11,9 +11,6 @@ from typing import Any, Optional, Dict, Set
|
|||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant import core, config as conf_util, config_entries, loader
|
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.const import EVENT_HOMEASSISTANT_CLOSE
|
||||||
from homeassistant.setup import async_setup_component
|
from homeassistant.setup import async_setup_component
|
||||||
from homeassistant.util.logging import AsyncHandler
|
from homeassistant.util.logging import AsyncHandler
|
||||||
@ -29,50 +26,16 @@ ERROR_LOG_FILENAME = 'home-assistant.log'
|
|||||||
# hass.data key for logging information.
|
# hass.data key for logging information.
|
||||||
DATA_LOGGING = 'logging'
|
DATA_LOGGING = 'logging'
|
||||||
|
|
||||||
LOGGING_COMPONENT = {'logger', 'system_log'}
|
CORE_INTEGRATIONS = ('homeassistant', 'persistent_notification')
|
||||||
|
LOGGING_INTEGRATIONS = {'logger', 'system_log'}
|
||||||
FIRST_INIT_COMPONENT = {
|
STAGE_1_INTEGRATIONS = {
|
||||||
|
# To record data
|
||||||
'recorder',
|
'recorder',
|
||||||
'mqtt',
|
# To make sure we forward data to other instances
|
||||||
'mqtt_eventstream',
|
'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],
|
async def async_from_config_dict(config: Dict[str, Any],
|
||||||
hass: core.HomeAssistant,
|
hass: core.HomeAssistant,
|
||||||
config_dir: Optional[str] = None,
|
config_dir: Optional[str] = None,
|
||||||
@ -115,70 +78,17 @@ async def async_from_config_dict(config: Dict[str, Any],
|
|||||||
"Further initialization aborted")
|
"Further initialization aborted")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
await hass.async_add_executor_job(
|
|
||||||
conf_util.process_ha_config_upgrade, hass)
|
|
||||||
|
|
||||||
# Make a copy because we are mutating it.
|
# Make a copy because we are mutating it.
|
||||||
config = OrderedDict(config)
|
config = OrderedDict(config)
|
||||||
|
|
||||||
# Merge packages
|
# Merge packages
|
||||||
conf_util.merge_packages_config(
|
await conf_util.merge_packages_config(
|
||||||
hass, config, core_config.get(conf_util.CONF_PACKAGES, {}))
|
hass, config, core_config.get(conf_util.CONF_PACKAGES, {}))
|
||||||
|
|
||||||
hass.config_entries = config_entries.ConfigEntries(hass, config)
|
hass.config_entries = config_entries.ConfigEntries(hass, config)
|
||||||
await hass.config_entries.async_initialize()
|
await hass.config_entries.async_initialize()
|
||||||
|
|
||||||
components = _get_components(hass, config)
|
await _async_set_up_integrations(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()
|
|
||||||
|
|
||||||
stop = time()
|
stop = time()
|
||||||
_LOGGER.info("Home Assistant initialized in %.2fs", stop-start)
|
_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
|
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,
|
async def async_from_config_file(config_path: str,
|
||||||
hass: core.HomeAssistant,
|
hass: core.HomeAssistant,
|
||||||
verbose: bool = False,
|
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,
|
async_enable_logging(hass, verbose, log_rotate_days, log_file,
|
||||||
log_no_color)
|
log_no_color)
|
||||||
|
|
||||||
|
await hass.async_add_executor_job(
|
||||||
|
conf_util.process_ha_config_upgrade, hass)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
config_dict = await hass.async_add_executor_job(
|
config_dict = await hass.async_add_executor_job(
|
||||||
conf_util.load_yaml_config_file, config_path)
|
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
|
@core.callback
|
||||||
def _get_components(hass: core.HomeAssistant,
|
def _get_domains(hass: core.HomeAssistant, config: Dict[str, Any]) -> Set[str]:
|
||||||
config: Dict[str, Any]) -> Set[str]:
|
"""Get domains of components to set up."""
|
||||||
"""Get components to set up."""
|
|
||||||
# Filter out the repeating and common config section [homeassistant]
|
# Filter out the repeating and common config section [homeassistant]
|
||||||
components = set(key.split(' ')[0] for key in config.keys()
|
domains = set(key.split(' ')[0] for key in config.keys()
|
||||||
if key != core.DOMAIN)
|
if key != core.DOMAIN)
|
||||||
|
|
||||||
# Add config entry domains
|
# 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
|
# Make sure the Hass.io component is loaded
|
||||||
if 'HASSIO' in os.environ:
|
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()
|
||||||
|
@ -13,8 +13,6 @@ from homeassistant.helpers import config_validation as cv
|
|||||||
from homeassistant.helpers import discovery
|
from homeassistant.helpers import discovery
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
|
||||||
REQUIREMENTS = ['abodepy==0.15.0']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
ATTRIBUTION = "Data provided by goabode.com"
|
ATTRIBUTION = "Data provided by goabode.com"
|
||||||
|
@ -8,8 +8,6 @@ from homeassistant.const import (
|
|||||||
|
|
||||||
from . import ATTRIBUTION, DOMAIN as ABODE_DOMAIN, AbodeDevice
|
from . import ATTRIBUTION, DOMAIN as ABODE_DOMAIN, AbodeDevice
|
||||||
|
|
||||||
DEPENDENCIES = ['abode']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
ICON = 'mdi:security'
|
ICON = 'mdi:security'
|
||||||
|
@ -7,8 +7,6 @@ from . import DOMAIN as ABODE_DOMAIN, AbodeAutomation, AbodeDevice
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEPENDENCIES = ['abode']
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up a sensor for an Abode device."""
|
"""Set up a sensor for an Abode device."""
|
||||||
|
@ -9,8 +9,6 @@ from homeassistant.util import Throttle
|
|||||||
|
|
||||||
from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
|
from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
|
||||||
|
|
||||||
DEPENDENCIES = ['abode']
|
|
||||||
|
|
||||||
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=90)
|
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=90)
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
@ -5,8 +5,6 @@ from homeassistant.components.cover import CoverDevice
|
|||||||
|
|
||||||
from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
|
from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
|
||||||
|
|
||||||
DEPENDENCIES = ['abode']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -10,8 +10,6 @@ from homeassistant.util.color import (
|
|||||||
|
|
||||||
from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
|
from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
|
||||||
|
|
||||||
DEPENDENCIES = ['abode']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -5,8 +5,6 @@ from homeassistant.components.lock import LockDevice
|
|||||||
|
|
||||||
from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
|
from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
|
||||||
|
|
||||||
DEPENDENCIES = ['abode']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
10
homeassistant/components/abode/manifest.json
Normal file
10
homeassistant/components/abode/manifest.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"domain": "abode",
|
||||||
|
"name": "Abode",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/abode",
|
||||||
|
"requirements": [
|
||||||
|
"abodepy==0.15.0"
|
||||||
|
],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
@ -8,8 +8,6 @@ from . import DOMAIN as ABODE_DOMAIN, AbodeDevice
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEPENDENCIES = ['abode']
|
|
||||||
|
|
||||||
# Sensor types: Name, icon
|
# Sensor types: Name, icon
|
||||||
SENSOR_TYPES = {
|
SENSOR_TYPES = {
|
||||||
'temp': ['Temperature', DEVICE_CLASS_TEMPERATURE],
|
'temp': ['Temperature', DEVICE_CLASS_TEMPERATURE],
|
||||||
|
@ -7,8 +7,6 @@ from . import DOMAIN as ABODE_DOMAIN, AbodeAutomation, AbodeDevice
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEPENDENCIES = ['abode']
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up Abode switch devices."""
|
"""Set up Abode switch devices."""
|
||||||
|
10
homeassistant/components/acer_projector/manifest.json
Normal file
10
homeassistant/components/acer_projector/manifest.json
Normal 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": []
|
||||||
|
}
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Use serial protocol of Acer projector to obtain state of the projector."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@ -14,8 +9,6 @@ from homeassistant.const import (
|
|||||||
STATE_ON, STATE_OFF, STATE_UNKNOWN, CONF_NAME, CONF_FILENAME)
|
STATE_ON, STATE_OFF, STATE_UNKNOWN, CONF_NAME, CONF_FILENAME)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
REQUIREMENTS = ['pyserial==3.1.1']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_TIMEOUT = 'timeout'
|
CONF_TIMEOUT = 'timeout'
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Support for Actiontec MI424WR (Verizon FIOS) routers."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
import telnetlib
|
import telnetlib
|
||||||
|
8
homeassistant/components/actiontec/manifest.json
Normal file
8
homeassistant/components/actiontec/manifest.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"domain": "actiontec",
|
||||||
|
"name": "Actiontec",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/actiontec",
|
||||||
|
"requirements": [],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
@ -4,14 +4,15 @@ import struct
|
|||||||
import logging
|
import logging
|
||||||
import ctypes
|
import ctypes
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
import asyncio
|
||||||
|
import async_timeout
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_DEVICE, CONF_IP_ADDRESS, CONF_PORT, EVENT_HOMEASSISTANT_STOP)
|
CONF_DEVICE, CONF_IP_ADDRESS, CONF_PORT, EVENT_HOMEASSISTANT_STOP)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.helpers.entity import Entity
|
||||||
REQUIREMENTS = ['pyads==3.0.7']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -31,6 +32,9 @@ CONF_ADS_VALUE = 'value'
|
|||||||
CONF_ADS_VAR = 'adsvar'
|
CONF_ADS_VAR = 'adsvar'
|
||||||
CONF_ADS_VAR_BRIGHTNESS = 'adsvar_brightness'
|
CONF_ADS_VAR_BRIGHTNESS = 'adsvar_brightness'
|
||||||
|
|
||||||
|
STATE_KEY_STATE = 'state'
|
||||||
|
STATE_KEY_BRIGHTNESS = 'brightness'
|
||||||
|
|
||||||
DOMAIN = 'ads'
|
DOMAIN = 'ads'
|
||||||
|
|
||||||
SERVICE_WRITE_DATA_BY_NAME = 'write_data_by_name'
|
SERVICE_WRITE_DATA_BY_NAME = 'write_data_by_name'
|
||||||
@ -154,28 +158,41 @@ class AdsHub:
|
|||||||
|
|
||||||
def write_by_name(self, name, value, plc_datatype):
|
def write_by_name(self, name, value, plc_datatype):
|
||||||
"""Write a value to the device."""
|
"""Write a value to the device."""
|
||||||
|
import pyads
|
||||||
with self._lock:
|
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):
|
def read_by_name(self, name, plc_datatype):
|
||||||
"""Read a value from the device."""
|
"""Read a value from the device."""
|
||||||
|
import pyads
|
||||||
with self._lock:
|
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):
|
def add_device_notification(self, name, plc_datatype, callback):
|
||||||
"""Add a notification to the ADS devices."""
|
"""Add a notification to the ADS devices."""
|
||||||
from pyads import NotificationAttrib
|
import pyads
|
||||||
attr = NotificationAttrib(ctypes.sizeof(plc_datatype))
|
attr = pyads.NotificationAttrib(ctypes.sizeof(plc_datatype))
|
||||||
|
|
||||||
with self._lock:
|
with self._lock:
|
||||||
hnotify, huser = self._client.add_device_notification(
|
try:
|
||||||
name, attr, self._device_notification_callback)
|
hnotify, huser = self._client.add_device_notification(
|
||||||
hnotify = int(hnotify)
|
name, attr, self._device_notification_callback)
|
||||||
self._notification_items[hnotify] = NotificationItem(
|
except pyads.ADSError as err:
|
||||||
hnotify, huser, name, plc_datatype, callback)
|
_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(
|
_LOGGER.debug(
|
||||||
"Added device notification %d for variable %s", hnotify, name)
|
"Added device notification %d for variable %s",
|
||||||
|
hnotify, name)
|
||||||
|
|
||||||
def _device_notification_callback(self, notification, name):
|
def _device_notification_callback(self, notification, name):
|
||||||
"""Handle device notifications."""
|
"""Handle device notifications."""
|
||||||
@ -210,3 +227,68 @@ class AdsHub:
|
|||||||
_LOGGER.warning("No callback available for this datatype")
|
_LOGGER.warning("No callback available for this datatype")
|
||||||
|
|
||||||
notification_item.callback(notification_item.name, value)
|
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
|
||||||
|
@ -8,13 +8,11 @@ from homeassistant.components.binary_sensor import (
|
|||||||
from homeassistant.const import CONF_DEVICE_CLASS, CONF_NAME
|
from homeassistant.const import CONF_DEVICE_CLASS, CONF_NAME
|
||||||
import homeassistant.helpers.config_validation as cv
|
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__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_NAME = 'ADS binary sensor'
|
DEFAULT_NAME = 'ADS binary sensor'
|
||||||
DEPENDENCIES = ['ads']
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Required(CONF_ADS_VAR): cv.string,
|
vol.Required(CONF_ADS_VAR): cv.string,
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): 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])
|
add_entities([ads_sensor])
|
||||||
|
|
||||||
|
|
||||||
class AdsBinarySensor(BinarySensorDevice):
|
class AdsBinarySensor(AdsEntity, BinarySensorDevice):
|
||||||
"""Representation of ADS binary sensors."""
|
"""Representation of ADS binary sensors."""
|
||||||
|
|
||||||
def __init__(self, ads_hub, name, ads_var, device_class):
|
def __init__(self, ads_hub, name, ads_var, device_class):
|
||||||
"""Initialize ADS binary sensor."""
|
"""Initialize ADS binary sensor."""
|
||||||
self._name = name
|
super().__init__(ads_hub, name, ads_var)
|
||||||
self._unique_id = ads_var
|
|
||||||
self._state = False
|
|
||||||
self._device_class = device_class or 'moving'
|
self._device_class = device_class or 'moving'
|
||||||
self._ads_hub = ads_hub
|
|
||||||
self.ads_var = ads_var
|
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Register device notification."""
|
"""Register device notification."""
|
||||||
def update(name, value):
|
await self.async_initialize_device(self._ads_var,
|
||||||
"""Handle device notifications."""
|
self._ads_hub.PLCTYPE_BOOL)
|
||||||
_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)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def is_on(self):
|
||||||
"""Return the default name of the binary sensor."""
|
"""Return True if the entity is on."""
|
||||||
return self._name
|
return self._state_dict[STATE_KEY_STATE]
|
||||||
|
|
||||||
@property
|
|
||||||
def unique_id(self):
|
|
||||||
"""Return an unique identifier for this entity."""
|
|
||||||
return self._unique_id
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def device_class(self):
|
def device_class(self):
|
||||||
"""Return the device class."""
|
"""Return the device class."""
|
||||||
return self._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
|
|
||||||
|
@ -8,12 +8,11 @@ from homeassistant.components.light import (
|
|||||||
from homeassistant.const import CONF_NAME
|
from homeassistant.const import CONF_NAME
|
||||||
import homeassistant.helpers.config_validation as cv
|
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__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
DEPENDENCIES = ['ads']
|
|
||||||
DEFAULT_NAME = 'ADS Light'
|
DEFAULT_NAME = 'ADS Light'
|
||||||
CONF_ADSVAR_BRIGHTNESS = 'adsvar_brightness'
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Required(CONF_ADS_VAR): cv.string,
|
vol.Required(CONF_ADS_VAR): cv.string,
|
||||||
vol.Optional(CONF_ADS_VAR_BRIGHTNESS): 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)
|
name = config.get(CONF_NAME)
|
||||||
|
|
||||||
add_entities([AdsLight(ads_hub, ads_var_enable, ads_var_brightness,
|
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."""
|
"""Representation of ADS light."""
|
||||||
|
|
||||||
def __init__(self, ads_hub, ads_var_enable, ads_var_brightness, name):
|
def __init__(self, ads_hub, ads_var_enable, ads_var_brightness, name):
|
||||||
"""Initialize AdsLight entity."""
|
"""Initialize AdsLight entity."""
|
||||||
self._ads_hub = ads_hub
|
super().__init__(ads_hub, name, ads_var_enable)
|
||||||
self._on_state = False
|
self._state_dict[STATE_KEY_BRIGHTNESS] = None
|
||||||
self._brightness = None
|
self._ads_var_brightness = ads_var_brightness
|
||||||
self._name = name
|
|
||||||
self._unique_id = ads_var_enable
|
|
||||||
self.ads_var_enable = ads_var_enable
|
|
||||||
self.ads_var_brightness = ads_var_brightness
|
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Register device notification."""
|
"""Register device notification."""
|
||||||
def update_on_state(name, value):
|
await self.async_initialize_device(self._ads_var,
|
||||||
"""Handle device notifications for state."""
|
self._ads_hub.PLCTYPE_BOOL)
|
||||||
_LOGGER.debug('Variable %s changed its value to %d', name, value)
|
|
||||||
self._on_state = value
|
|
||||||
self.schedule_update_ha_state()
|
|
||||||
|
|
||||||
def update_brightness(name, value):
|
if self._ads_var_brightness is not None:
|
||||||
"""Handle device notification for brightness."""
|
await self.async_initialize_device(self._ads_var_brightness,
|
||||||
_LOGGER.debug('Variable %s changed its value to %d', name, value)
|
self._ads_hub.PLCTYPE_UINT,
|
||||||
self._brightness = value
|
STATE_KEY_BRIGHTNESS)
|
||||||
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
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def brightness(self):
|
def brightness(self):
|
||||||
"""Return the brightness of the light (0..255)."""
|
"""Return the brightness of the light (0..255)."""
|
||||||
return self._brightness
|
return self._state_dict[STATE_KEY_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
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_features(self):
|
def supported_features(self):
|
||||||
"""Flag supported features."""
|
"""Flag supported features."""
|
||||||
support = 0
|
support = 0
|
||||||
if self.ads_var_brightness is not None:
|
if self._ads_var_brightness is not None:
|
||||||
support = SUPPORT_BRIGHTNESS
|
support = SUPPORT_BRIGHTNESS
|
||||||
return support
|
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):
|
def turn_on(self, **kwargs):
|
||||||
"""Turn the light on or set a specific dimmer value."""
|
"""Turn the light on or set a specific dimmer value."""
|
||||||
brightness = kwargs.get(ATTR_BRIGHTNESS)
|
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)
|
self._ads_hub.PLCTYPE_BOOL)
|
||||||
|
|
||||||
if self.ads_var_brightness is not None and brightness is not None:
|
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.write_by_name(self._ads_var_brightness, brightness,
|
||||||
self._ads_hub.PLCTYPE_UINT)
|
self._ads_hub.PLCTYPE_UINT)
|
||||||
|
|
||||||
def turn_off(self, **kwargs):
|
def turn_off(self, **kwargs):
|
||||||
"""Turn the light off."""
|
"""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)
|
self._ads_hub.PLCTYPE_BOOL)
|
||||||
|
10
homeassistant/components/ads/manifest.json
Normal file
10
homeassistant/components/ads/manifest.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"domain": "ads",
|
||||||
|
"name": "Ads",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/ads",
|
||||||
|
"requirements": [
|
||||||
|
"pyads==3.0.7"
|
||||||
|
],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
@ -7,15 +7,13 @@ from homeassistant.components import ads
|
|||||||
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
from homeassistant.components.sensor import PLATFORM_SCHEMA
|
||||||
from homeassistant.const import CONF_NAME, CONF_UNIT_OF_MEASUREMENT
|
from homeassistant.const import CONF_NAME, CONF_UNIT_OF_MEASUREMENT
|
||||||
import homeassistant.helpers.config_validation as cv
|
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__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_NAME = "ADS sensor"
|
DEFAULT_NAME = "ADS sensor"
|
||||||
DEPENDENCIES = ['ads']
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Required(CONF_ADS_VAR): cv.string,
|
vol.Required(CONF_ADS_VAR): cv.string,
|
||||||
vol.Optional(CONF_ADS_FACTOR): cv.positive_int,
|
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])
|
add_entities([entity])
|
||||||
|
|
||||||
|
|
||||||
class AdsSensor(Entity):
|
class AdsSensor(AdsEntity):
|
||||||
"""Representation of an ADS sensor entity."""
|
"""Representation of an ADS sensor entity."""
|
||||||
|
|
||||||
def __init__(self, ads_hub, ads_var, ads_type, name, unit_of_measurement,
|
def __init__(self, ads_hub, ads_var, ads_type, name, unit_of_measurement,
|
||||||
factor):
|
factor):
|
||||||
"""Initialize AdsSensor entity."""
|
"""Initialize AdsSensor entity."""
|
||||||
self._ads_hub = ads_hub
|
super().__init__(ads_hub, name, ads_var)
|
||||||
self._name = name
|
|
||||||
self._unique_id = ads_var
|
|
||||||
self._value = None
|
|
||||||
self._unit_of_measurement = unit_of_measurement
|
self._unit_of_measurement = unit_of_measurement
|
||||||
self.ads_var = ads_var
|
self._ads_type = ads_type
|
||||||
self.ads_type = ads_type
|
self._factor = factor
|
||||||
self.factor = factor
|
|
||||||
|
|
||||||
async def async_added_to_hass(self):
|
async def async_added_to_hass(self):
|
||||||
"""Register device notification."""
|
"""Register device notification."""
|
||||||
def update(name, value):
|
await self.async_initialize_device(
|
||||||
"""Handle device notifications."""
|
self._ads_var,
|
||||||
_LOGGER.debug("Variable %s changed its value to %d", name, value)
|
self._ads_hub.ADS_TYPEMAP[self._ads_type],
|
||||||
|
STATE_KEY_STATE,
|
||||||
# If factor is set use it otherwise not
|
self._factor)
|
||||||
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
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def state(self):
|
def state(self):
|
||||||
"""Return the state of the device."""
|
"""Return the state of the device."""
|
||||||
return self._value
|
return self._state_dict[STATE_KEY_STATE]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def unit_of_measurement(self):
|
def unit_of_measurement(self):
|
||||||
"""Return the unit of measurement."""
|
"""Return the unit of measurement."""
|
||||||
return self._unit_of_measurement
|
return self._unit_of_measurement
|
||||||
|
|
||||||
@property
|
|
||||||
def should_poll(self):
|
|
||||||
"""Return False because entity pushes its state."""
|
|
||||||
return False
|
|
||||||
|
@ -3,17 +3,14 @@ import logging
|
|||||||
|
|
||||||
import voluptuous as vol
|
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
|
from homeassistant.const import CONF_NAME
|
||||||
import homeassistant.helpers.config_validation as cv
|
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__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEPENDENCIES = ['ads']
|
|
||||||
|
|
||||||
DEFAULT_NAME = 'ADS Switch'
|
DEFAULT_NAME = 'ADS Switch'
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
@ -29,58 +26,28 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
|
|||||||
name = config.get(CONF_NAME)
|
name = config.get(CONF_NAME)
|
||||||
ads_var = config.get(CONF_ADS_VAR)
|
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."""
|
"""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):
|
async def async_added_to_hass(self):
|
||||||
"""Register device notification."""
|
"""Register device notification."""
|
||||||
def update(name, value):
|
await self.async_initialize_device(self._ads_var,
|
||||||
"""Handle device notification."""
|
self._ads_hub.PLCTYPE_BOOL)
|
||||||
_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)
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self):
|
def is_on(self):
|
||||||
"""Return if the switch is turned on."""
|
"""Return True if the entity is on."""
|
||||||
return self._on_state
|
return self._state_dict[STATE_KEY_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
|
|
||||||
|
|
||||||
def turn_on(self, **kwargs):
|
def turn_on(self, **kwargs):
|
||||||
"""Turn the switch on."""
|
"""Turn the switch on."""
|
||||||
self._ads_hub.write_by_name(
|
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):
|
def turn_off(self, **kwargs):
|
||||||
"""Turn the switch off."""
|
"""Turn the switch off."""
|
||||||
self._ads_hub.write_by_name(
|
self._ads_hub.write_by_name(
|
||||||
self.ads_var, False, self._ads_hub.PLCTYPE_BOOL)
|
self._ads_var, False, self._ads_hub.PLCTYPE_BOOL)
|
||||||
|
2
homeassistant/components/aftership/const.py
Normal file
2
homeassistant/components/aftership/const.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
"""Constants for the Aftership integration."""
|
||||||
|
DOMAIN = 'aftership'
|
10
homeassistant/components/aftership/manifest.json
Normal file
10
homeassistant/components/aftership/manifest.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"domain": "aftership",
|
||||||
|
"name": "Aftership",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/aftership",
|
||||||
|
"requirements": [
|
||||||
|
"pyaftership==0.1.2"
|
||||||
|
],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Support for non-delivered packages recorded in AfterShip."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
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.const import ATTR_ATTRIBUTION, CONF_API_KEY, CONF_NAME
|
||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_send
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
|
from .const import DOMAIN
|
||||||
REQUIREMENTS = ['pyaftership==0.1.2']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
ATTRIBUTION = 'Information provided by AfterShip'
|
ATTRIBUTION = 'Information provided by AfterShip'
|
||||||
|
ATTR_TRACKINGS = 'trackings'
|
||||||
|
|
||||||
|
BASE = 'https://track.aftership.com/'
|
||||||
|
|
||||||
CONF_SLUG = 'slug'
|
CONF_SLUG = 'slug'
|
||||||
CONF_TITLE = 'title'
|
CONF_TITLE = 'title'
|
||||||
CONF_TRACKING_NUMBER = 'tracking_number'
|
CONF_TRACKING_NUMBER = 'tracking_number'
|
||||||
|
|
||||||
DEFAULT_NAME = 'aftership'
|
DEFAULT_NAME = 'aftership'
|
||||||
|
UPDATE_TOPIC = DOMAIN + '_update'
|
||||||
|
|
||||||
ICON = 'mdi:package-variant-closed'
|
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({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Required(CONF_API_KEY): cv.string,
|
vol.Required(CONF_API_KEY): cv.string,
|
||||||
@ -56,7 +71,40 @@ async def async_setup_platform(
|
|||||||
aftership.meta)
|
aftership.meta)
|
||||||
return
|
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):
|
class AfterShipSensor(Entity):
|
||||||
@ -94,8 +142,18 @@ class AfterShipSensor(Entity):
|
|||||||
"""Icon to use in the frontend."""
|
"""Icon to use in the frontend."""
|
||||||
return ICON
|
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)
|
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||||
async def async_update(self):
|
async def async_update(self, **kwargs):
|
||||||
"""Get the latest data from the AfterShip API."""
|
"""Get the latest data from the AfterShip API."""
|
||||||
await self.aftership.get_trackings()
|
await self.aftership.get_trackings()
|
||||||
|
|
||||||
@ -109,12 +167,29 @@ class AfterShipSensor(Entity):
|
|||||||
|
|
||||||
status_to_ignore = {'delivered'}
|
status_to_ignore = {'delivered'}
|
||||||
status_counts = {}
|
status_counts = {}
|
||||||
|
trackings = []
|
||||||
not_delivered_count = 0
|
not_delivered_count = 0
|
||||||
|
|
||||||
for tracking in self.aftership.trackings['trackings']:
|
for track in self.aftership.trackings['trackings']:
|
||||||
status = tracking['tag'].lower()
|
status = track['tag'].lower()
|
||||||
name = tracking['tracking_number']
|
name = (
|
||||||
status_counts[status] = status_counts.get(status, 0)+1
|
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:
|
if status not in status_to_ignore:
|
||||||
not_delivered_count += 1
|
not_delivered_count += 1
|
||||||
else:
|
else:
|
||||||
@ -122,7 +197,8 @@ class AfterShipSensor(Entity):
|
|||||||
|
|
||||||
self._attributes = {
|
self._attributes = {
|
||||||
ATTR_ATTRIBUTION: ATTRIBUTION,
|
ATTR_ATTRIBUTION: ATTRIBUTION,
|
||||||
**status_counts
|
**status_counts,
|
||||||
|
ATTR_TRACKINGS: trackings,
|
||||||
}
|
}
|
||||||
|
|
||||||
self._state = not_delivered_count
|
self._state = not_delivered_count
|
||||||
|
24
homeassistant/components/aftership/services.yaml
Normal file
24
homeassistant/components/aftership/services.yaml
Normal 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'
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Component for handling Air Quality data for your location."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
8
homeassistant/components/air_quality/manifest.json
Normal file
8
homeassistant/components/air_quality/manifest.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"domain": "air_quality",
|
||||||
|
"name": "Air quality",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/air_quality",
|
||||||
|
"requirements": [],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
12
homeassistant/components/airvisual/manifest.json
Normal file
12
homeassistant/components/airvisual/manifest.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Support for AirVisual air quality sensors."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from datetime import timedelta
|
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.helpers.entity import Entity
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
|
|
||||||
REQUIREMENTS = ['pyairvisual==3.0.1']
|
|
||||||
_LOGGER = getLogger(__name__)
|
_LOGGER = getLogger(__name__)
|
||||||
|
|
||||||
ATTR_CITY = 'city'
|
ATTR_CITY = 'city'
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Platform for the Aladdin Connect cover component."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -14,8 +9,6 @@ from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD, STATE_CLOSED,
|
|||||||
STATE_OPENING, STATE_CLOSING, STATE_OPEN)
|
STATE_OPENING, STATE_CLOSING, STATE_OPEN)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
REQUIREMENTS = ['aladdin_connect==0.3']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
NOTIFICATION_ID = 'aladdin_notification'
|
NOTIFICATION_ID = 'aladdin_notification'
|
||||||
|
10
homeassistant/components/aladdin_connect/manifest.json
Normal file
10
homeassistant/components/aladdin_connect/manifest.json
Normal 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": []
|
||||||
|
}
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Component to interface with an alarm control panel."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
10
homeassistant/components/alarm_control_panel/manifest.json
Normal file
10
homeassistant/components/alarm_control_panel/manifest.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
@ -10,8 +10,6 @@ from homeassistant.helpers.discovery import load_platform
|
|||||||
from homeassistant.util import dt as dt_util
|
from homeassistant.util import dt as dt_util
|
||||||
from homeassistant.components.binary_sensor import DEVICE_CLASSES_SCHEMA
|
from homeassistant.components.binary_sensor import DEVICE_CLASSES_SCHEMA
|
||||||
|
|
||||||
REQUIREMENTS = ['alarmdecoder==1.13.2']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DOMAIN = 'alarmdecoder'
|
DOMAIN = 'alarmdecoder'
|
||||||
|
@ -13,8 +13,6 @@ from . import DATA_AD, SIGNAL_PANEL_MESSAGE
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEPENDENCIES = ['alarmdecoder']
|
|
||||||
|
|
||||||
SERVICE_ALARM_TOGGLE_CHIME = 'alarmdecoder_alarm_toggle_chime'
|
SERVICE_ALARM_TOGGLE_CHIME = 'alarmdecoder_alarm_toggle_chime'
|
||||||
ALARM_TOGGLE_CHIME_SCHEMA = vol.Schema({
|
ALARM_TOGGLE_CHIME_SCHEMA = vol.Schema({
|
||||||
vol.Required(ATTR_CODE): cv.string,
|
vol.Required(ATTR_CODE): cv.string,
|
||||||
|
@ -8,8 +8,6 @@ from . import (
|
|||||||
CONF_ZONE_RFID, CONF_ZONE_TYPE, CONF_ZONES, SIGNAL_REL_MESSAGE,
|
CONF_ZONE_RFID, CONF_ZONE_TYPE, CONF_ZONES, SIGNAL_REL_MESSAGE,
|
||||||
SIGNAL_RFX_MESSAGE, SIGNAL_ZONE_FAULT, SIGNAL_ZONE_RESTORE, ZONE_SCHEMA)
|
SIGNAL_RFX_MESSAGE, SIGNAL_ZONE_FAULT, SIGNAL_ZONE_RESTORE, ZONE_SCHEMA)
|
||||||
|
|
||||||
DEPENDENCIES = ['alarmdecoder']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
ATTR_RF_BIT0 = 'rf_bit0'
|
ATTR_RF_BIT0 = 'rf_bit0'
|
||||||
|
10
homeassistant/components/alarmdecoder/manifest.json
Normal file
10
homeassistant/components/alarmdecoder/manifest.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"domain": "alarmdecoder",
|
||||||
|
"name": "Alarmdecoder",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/alarmdecoder",
|
||||||
|
"requirements": [
|
||||||
|
"alarmdecoder==1.13.2"
|
||||||
|
],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
@ -7,8 +7,6 @@ from . import SIGNAL_PANEL_MESSAGE
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEPENDENCIES = ['alarmdecoder']
|
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_entities, discovery_info=None):
|
def setup_platform(hass, config, add_entities, discovery_info=None):
|
||||||
"""Set up for AlarmDecoder sensor devices."""
|
"""Set up for AlarmDecoder sensor devices."""
|
||||||
|
0
homeassistant/components/alarmdecoder/services.yaml
Normal file
0
homeassistant/components/alarmdecoder/services.yaml
Normal file
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Interfaces with Alarm.com alarm control panels."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
|
|
||||||
@ -17,8 +12,6 @@ from homeassistant.const import (
|
|||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
REQUIREMENTS = ['pyalarmdotcom==0.3.2']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEFAULT_NAME = 'Alarm.com'
|
DEFAULT_NAME = 'Alarm.com'
|
||||||
|
10
homeassistant/components/alarmdotcom/manifest.json
Normal file
10
homeassistant/components/alarmdotcom/manifest.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"domain": "alarmdotcom",
|
||||||
|
"name": "Alarmdotcom",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/alarmdotcom",
|
||||||
|
"requirements": [
|
||||||
|
"pyalarmdotcom==0.3.2"
|
||||||
|
],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
8
homeassistant/components/alert/manifest.json
Normal file
8
homeassistant/components/alert/manifest.json
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"domain": "alert",
|
||||||
|
"name": "Alert",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/alert",
|
||||||
|
"requirements": [],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
@ -17,8 +17,6 @@ _LOGGER = logging.getLogger(__name__)
|
|||||||
CONF_FLASH_BRIEFINGS = 'flash_briefings'
|
CONF_FLASH_BRIEFINGS = 'flash_briefings'
|
||||||
CONF_SMART_HOME = 'smart_home'
|
CONF_SMART_HOME = 'smart_home'
|
||||||
|
|
||||||
DEPENDENCIES = ['http']
|
|
||||||
|
|
||||||
ALEXA_ENTITY_SCHEMA = vol.Schema({
|
ALEXA_ENTITY_SCHEMA = vol.Schema({
|
||||||
vol.Optional(smart_home.CONF_DESCRIPTION): cv.string,
|
vol.Optional(smart_home.CONF_DESCRIPTION): cv.string,
|
||||||
vol.Optional(smart_home.CONF_DISPLAY_CATEGORIES): cv.string,
|
vol.Optional(smart_home.CONF_DISPLAY_CATEGORIES): cv.string,
|
||||||
|
10
homeassistant/components/alexa/manifest.json
Normal file
10
homeassistant/components/alexa/manifest.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"domain": "alexa",
|
||||||
|
"name": "Alexa",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/alexa",
|
||||||
|
"requirements": [],
|
||||||
|
"dependencies": [
|
||||||
|
"http"
|
||||||
|
],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
0
homeassistant/components/alexa/services.yaml
Normal file
0
homeassistant/components/alexa/services.yaml
Normal file
12
homeassistant/components/alpha_vantage/manifest.json
Normal file
12
homeassistant/components/alpha_vantage/manifest.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Stock market information from Alpha Vantage."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
@ -15,8 +10,6 @@ from homeassistant.const import (
|
|||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
|
|
||||||
REQUIREMENTS = ['alpha_vantage==2.1.0']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
ATTR_CLOSE = 'close'
|
ATTR_CLOSE = 'close'
|
||||||
|
12
homeassistant/components/amazon_polly/manifest.json
Normal file
12
homeassistant/components/amazon_polly/manifest.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Support for the Amazon Polly text to speech service."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -11,8 +6,6 @@ import voluptuous as vol
|
|||||||
from homeassistant.components.tts import PLATFORM_SCHEMA, Provider
|
from homeassistant.components.tts import PLATFORM_SCHEMA, Provider
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
REQUIREMENTS = ['boto3==1.9.16']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_REGION = 'region_name'
|
CONF_REGION = 'region_name'
|
||||||
|
@ -1,9 +1,19 @@
|
|||||||
{
|
{
|
||||||
"config": {
|
"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": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
|
"data": {
|
||||||
|
"api_key": "Clave API",
|
||||||
|
"app_key": "Clave de aplicaci\u00f3n"
|
||||||
|
},
|
||||||
"title": "Completa tu informaci\u00f3n"
|
"title": "Completa tu informaci\u00f3n"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"title": "Ambient PWS"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -13,6 +13,7 @@
|
|||||||
},
|
},
|
||||||
"title": "Veuillez saisir vos informations"
|
"title": "Veuillez saisir vos informations"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"title": "Ambient PWS"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -11,7 +11,7 @@
|
|||||||
"api_key": "API \ud0a4",
|
"api_key": "API \ud0a4",
|
||||||
"app_key": "Application \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"
|
"title": "Ambient PWS"
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
{
|
{
|
||||||
"config": {
|
"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": {
|
"step": {
|
||||||
"user": {
|
"user": {
|
||||||
"data": {
|
"data": {
|
||||||
|
@ -20,8 +20,6 @@ from .const import (
|
|||||||
ATTR_LAST_DATA, CONF_APP_KEY, DATA_CLIENT, DOMAIN, TOPIC_UPDATE,
|
ATTR_LAST_DATA, CONF_APP_KEY, DATA_CLIENT, DOMAIN, TOPIC_UPDATE,
|
||||||
TYPE_BINARY_SENSOR, TYPE_SENSOR)
|
TYPE_BINARY_SENSOR, TYPE_SENSOR)
|
||||||
|
|
||||||
REQUIREMENTS = ['aioambient==0.2.0']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DATA_CONFIG = 'config'
|
DATA_CONFIG = 'config'
|
||||||
@ -329,6 +327,8 @@ class AmbientStation:
|
|||||||
"""Define a handler to fire when the websocket is connected."""
|
"""Define a handler to fire when the websocket is connected."""
|
||||||
_LOGGER.info('Connected to websocket')
|
_LOGGER.info('Connected to websocket')
|
||||||
_LOGGER.debug('Watchdog starting')
|
_LOGGER.debug('Watchdog starting')
|
||||||
|
if self._watchdog_listener:
|
||||||
|
self._watchdog_listener()
|
||||||
self._watchdog_listener = async_call_later(
|
self._watchdog_listener = async_call_later(
|
||||||
self._hass, DEFAULT_WATCHDOG_SECONDS, _ws_reconnect)
|
self._hass, DEFAULT_WATCHDOG_SECONDS, _ws_reconnect)
|
||||||
|
|
||||||
|
@ -12,8 +12,6 @@ from .const import ATTR_LAST_DATA, DATA_CLIENT, DOMAIN, TYPE_BINARY_SENSOR
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEPENDENCIES = ['ambient_station']
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass, config, async_add_entities, discovery_info=None):
|
hass, config, async_add_entities, discovery_info=None):
|
||||||
|
12
homeassistant/components/ambient_station/manifest.json
Normal file
12
homeassistant/components/ambient_station/manifest.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
@ -8,8 +8,6 @@ from .const import ATTR_LAST_DATA, DATA_CLIENT, DOMAIN, TYPE_SENSOR
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEPENDENCIES = ['ambient_station']
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass, config, async_add_entities, discovery_info=None):
|
hass, config, async_add_entities, discovery_info=None):
|
||||||
|
@ -7,14 +7,11 @@ import voluptuous as vol
|
|||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
CONF_NAME, CONF_HOST, CONF_PORT, CONF_USERNAME, CONF_PASSWORD,
|
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
|
from homeassistant.helpers import discovery
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
|
|
||||||
REQUIREMENTS = ['amcrest==1.2.7']
|
|
||||||
DEPENDENCIES = ['ffmpeg']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_AUTHENTICATION = 'authentication'
|
CONF_AUTHENTICATION = 'authentication'
|
||||||
@ -52,9 +49,14 @@ STREAM_SOURCE_LIST = {
|
|||||||
'rtsp': 2,
|
'rtsp': 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BINARY_SENSORS = {
|
||||||
|
'motion_detected': 'Motion Detected'
|
||||||
|
}
|
||||||
|
|
||||||
# Sensor types are defined like: Name, units, icon
|
# Sensor types are defined like: Name, units, icon
|
||||||
|
SENSOR_MOTION_DETECTOR = 'motion_detector'
|
||||||
SENSORS = {
|
SENSORS = {
|
||||||
'motion_detector': ['Motion Detected', None, 'mdi:run'],
|
SENSOR_MOTION_DETECTOR: ['Motion Detected', None, 'mdi:run'],
|
||||||
'sdcard': ['SD Used', '%', 'mdi:sd'],
|
'sdcard': ['SD Used', '%', 'mdi:sd'],
|
||||||
'ptz_preset': ['PTZ Preset', None, 'mdi:camera-iris'],
|
'ptz_preset': ['PTZ Preset', None, 'mdi:camera-iris'],
|
||||||
}
|
}
|
||||||
@ -65,28 +67,49 @@ SWITCHES = {
|
|||||||
'motion_recording': ['Motion Recording', 'mdi:record-rec']
|
'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({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
DOMAIN: vol.All(cv.ensure_list, [vol.Schema({
|
DOMAIN: vol.All(cv.ensure_list, [AMCREST_SCHEMA], _has_unique_names)
|
||||||
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)]),
|
|
||||||
})])
|
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
|
|
||||||
@ -94,20 +117,24 @@ def setup(hass, config):
|
|||||||
"""Set up the Amcrest IP Camera component."""
|
"""Set up the Amcrest IP Camera component."""
|
||||||
from amcrest import AmcrestCamera, AmcrestError
|
from amcrest import AmcrestCamera, AmcrestError
|
||||||
|
|
||||||
hass.data[DATA_AMCREST] = {}
|
hass.data.setdefault(DATA_AMCREST, {})
|
||||||
amcrest_cams = config[DOMAIN]
|
amcrest_cams = config[DOMAIN]
|
||||||
|
|
||||||
for device in amcrest_cams:
|
for device in amcrest_cams:
|
||||||
|
name = device[CONF_NAME]
|
||||||
|
username = device[CONF_USERNAME]
|
||||||
|
password = device[CONF_PASSWORD]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
camera = AmcrestCamera(device.get(CONF_HOST),
|
camera = AmcrestCamera(device[CONF_HOST],
|
||||||
device.get(CONF_PORT),
|
device[CONF_PORT],
|
||||||
device.get(CONF_USERNAME),
|
username,
|
||||||
device.get(CONF_PASSWORD)).camera
|
password).camera
|
||||||
# pylint: disable=pointless-statement
|
# pylint: disable=pointless-statement
|
||||||
camera.current_time
|
camera.current_time
|
||||||
|
|
||||||
except AmcrestError as ex:
|
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(
|
hass.components.persistent_notification.create(
|
||||||
'Error: {}<br />'
|
'Error: {}<br />'
|
||||||
'You will need to restart hass after fixing.'
|
'You will need to restart hass after fixing.'
|
||||||
@ -116,23 +143,19 @@ def setup(hass, config):
|
|||||||
notification_id=NOTIFICATION_ID)
|
notification_id=NOTIFICATION_ID)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
ffmpeg_arguments = device.get(CONF_FFMPEG_ARGUMENTS)
|
ffmpeg_arguments = device[CONF_FFMPEG_ARGUMENTS]
|
||||||
name = device.get(CONF_NAME)
|
resolution = RESOLUTION_LIST[device[CONF_RESOLUTION]]
|
||||||
resolution = RESOLUTION_LIST[device.get(CONF_RESOLUTION)]
|
binary_sensors = device.get(CONF_BINARY_SENSORS)
|
||||||
sensors = device.get(CONF_SENSORS)
|
sensors = device.get(CONF_SENSORS)
|
||||||
switches = device.get(CONF_SWITCHES)
|
switches = device.get(CONF_SWITCHES)
|
||||||
stream_source = STREAM_SOURCE_LIST[device.get(CONF_STREAM_SOURCE)]
|
stream_source = STREAM_SOURCE_LIST[device[CONF_STREAM_SOURCE]]
|
||||||
|
|
||||||
username = device.get(CONF_USERNAME)
|
|
||||||
password = device.get(CONF_PASSWORD)
|
|
||||||
|
|
||||||
# currently aiohttp only works with basic authentication
|
# currently aiohttp only works with basic authentication
|
||||||
# only valid for mjpeg streaming
|
# only valid for mjpeg streaming
|
||||||
if username is not None and password is not None:
|
if device[CONF_AUTHENTICATION] == HTTP_BASIC_AUTHENTICATION:
|
||||||
if device.get(CONF_AUTHENTICATION) == HTTP_BASIC_AUTHENTICATION:
|
authentication = aiohttp.BasicAuth(username, password)
|
||||||
authentication = aiohttp.BasicAuth(username, password)
|
else:
|
||||||
else:
|
authentication = None
|
||||||
authentication = None
|
|
||||||
|
|
||||||
hass.data[DATA_AMCREST][name] = AmcrestDevice(
|
hass.data[DATA_AMCREST][name] = AmcrestDevice(
|
||||||
camera, name, authentication, ffmpeg_arguments, stream_source,
|
camera, name, authentication, ffmpeg_arguments, stream_source,
|
||||||
@ -143,6 +166,13 @@ def setup(hass, config):
|
|||||||
CONF_NAME: name,
|
CONF_NAME: name,
|
||||||
}, config)
|
}, config)
|
||||||
|
|
||||||
|
if binary_sensors:
|
||||||
|
discovery.load_platform(
|
||||||
|
hass, 'binary_sensor', DOMAIN, {
|
||||||
|
CONF_NAME: name,
|
||||||
|
CONF_BINARY_SENSORS: binary_sensors
|
||||||
|
}, config)
|
||||||
|
|
||||||
if sensors:
|
if sensors:
|
||||||
discovery.load_platform(
|
discovery.load_platform(
|
||||||
hass, 'sensor', DOMAIN, {
|
hass, 'sensor', DOMAIN, {
|
||||||
@ -157,7 +187,7 @@ def setup(hass, config):
|
|||||||
CONF_SWITCHES: switches
|
CONF_SWITCHES: switches
|
||||||
}, config)
|
}, config)
|
||||||
|
|
||||||
return True
|
return len(hass.data[DATA_AMCREST]) >= 1
|
||||||
|
|
||||||
|
|
||||||
class AmcrestDevice:
|
class AmcrestDevice:
|
||||||
|
69
homeassistant/components/amcrest/binary_sensor.py
Normal file
69
homeassistant/components/amcrest/binary_sensor.py
Normal 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)
|
@ -3,7 +3,7 @@ import asyncio
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from homeassistant.components.camera import (
|
from homeassistant.components.camera import (
|
||||||
Camera, SUPPORT_STREAM)
|
Camera, SUPPORT_ON_OFF, SUPPORT_STREAM)
|
||||||
from homeassistant.components.ffmpeg import DATA_FFMPEG
|
from homeassistant.components.ffmpeg import DATA_FFMPEG
|
||||||
from homeassistant.const import CONF_NAME
|
from homeassistant.const import CONF_NAME
|
||||||
from homeassistant.helpers.aiohttp_client import (
|
from homeassistant.helpers.aiohttp_client import (
|
||||||
@ -12,8 +12,6 @@ from homeassistant.helpers.aiohttp_client import (
|
|||||||
|
|
||||||
from . import DATA_AMCREST, STREAM_SOURCE_LIST, TIMEOUT
|
from . import DATA_AMCREST, STREAM_SOURCE_LIST, TIMEOUT
|
||||||
|
|
||||||
DEPENDENCIES = ['amcrest', 'ffmpeg']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_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)
|
async_add_entities([AmcrestCam(hass, amcrest)], True)
|
||||||
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class AmcrestCam(Camera):
|
class AmcrestCam(Camera):
|
||||||
"""An implementation of an Amcrest IP camera."""
|
"""An implementation of an Amcrest IP camera."""
|
||||||
@ -39,18 +35,23 @@ class AmcrestCam(Camera):
|
|||||||
super(AmcrestCam, self).__init__()
|
super(AmcrestCam, self).__init__()
|
||||||
self._name = amcrest.name
|
self._name = amcrest.name
|
||||||
self._camera = amcrest.device
|
self._camera = amcrest.device
|
||||||
self._base_url = self._camera.get_base_url()
|
|
||||||
self._ffmpeg = hass.data[DATA_FFMPEG]
|
self._ffmpeg = hass.data[DATA_FFMPEG]
|
||||||
self._ffmpeg_arguments = amcrest.ffmpeg_arguments
|
self._ffmpeg_arguments = amcrest.ffmpeg_arguments
|
||||||
self._stream_source = amcrest.stream_source
|
self._stream_source = amcrest.stream_source
|
||||||
self._resolution = amcrest.resolution
|
self._resolution = amcrest.resolution
|
||||||
self._token = self._auth = amcrest.authentication
|
self._token = self._auth = amcrest.authentication
|
||||||
|
self._is_recording = False
|
||||||
|
self._model = None
|
||||||
self._snapshot_lock = asyncio.Lock()
|
self._snapshot_lock = asyncio.Lock()
|
||||||
|
|
||||||
async def async_camera_image(self):
|
async def async_camera_image(self):
|
||||||
"""Return a still image response from the camera."""
|
"""Return a still image response from the camera."""
|
||||||
from amcrest import AmcrestError
|
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:
|
async with self._snapshot_lock:
|
||||||
try:
|
try:
|
||||||
# Send the request to snap a picture and return raw jpg data
|
# Send the request to snap a picture and return raw jpg data
|
||||||
@ -59,7 +60,8 @@ class AmcrestCam(Camera):
|
|||||||
return response.data
|
return response.data
|
||||||
except AmcrestError as error:
|
except AmcrestError as error:
|
||||||
_LOGGER.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
|
return None
|
||||||
|
|
||||||
async def handle_async_mjpeg_stream(self, request):
|
async def handle_async_mjpeg_stream(self, request):
|
||||||
@ -94,6 +96,8 @@ class AmcrestCam(Camera):
|
|||||||
finally:
|
finally:
|
||||||
await stream.close()
|
await stream.close()
|
||||||
|
|
||||||
|
# Entity property overrides
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
"""Return the name of this camera."""
|
"""Return the name of this camera."""
|
||||||
@ -102,9 +106,80 @@ class AmcrestCam(Camera):
|
|||||||
@property
|
@property
|
||||||
def supported_features(self):
|
def supported_features(self):
|
||||||
"""Return supported features."""
|
"""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
|
@property
|
||||||
def stream_source(self):
|
def stream_source(self):
|
||||||
"""Return the source of the stream."""
|
"""Return the source of the stream."""
|
||||||
return self._camera.rtsp_url(typeno=self._resolution)
|
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()
|
||||||
|
12
homeassistant/components/amcrest/manifest.json
Normal file
12
homeassistant/components/amcrest/manifest.json
Normal 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": []
|
||||||
|
}
|
@ -7,8 +7,6 @@ from homeassistant.helpers.entity import Entity
|
|||||||
|
|
||||||
from . import DATA_AMCREST, SENSORS
|
from . import DATA_AMCREST, SENSORS
|
||||||
|
|
||||||
DEPENDENCIES = ['amcrest']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
SCAN_INTERVAL = timedelta(seconds=10)
|
SCAN_INTERVAL = timedelta(seconds=10)
|
||||||
@ -30,7 +28,6 @@ async def async_setup_platform(
|
|||||||
AmcrestSensor(amcrest.name, amcrest.device, sensor_type))
|
AmcrestSensor(amcrest.name, amcrest.device, sensor_type))
|
||||||
|
|
||||||
async_add_entities(amcrest_sensors, True)
|
async_add_entities(amcrest_sensors, True)
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class AmcrestSensor(Entity):
|
class AmcrestSensor(Entity):
|
||||||
@ -75,19 +72,6 @@ class AmcrestSensor(Entity):
|
|||||||
"""Get the latest data and updates the state."""
|
"""Get the latest data and updates the state."""
|
||||||
_LOGGER.debug("Pulling data from %s sensor.", self._name)
|
_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':
|
if self._sensor_type == 'motion_detector':
|
||||||
self._state = self._camera.is_motion_detected
|
self._state = self._camera.is_motion_detected
|
||||||
self._attrs['Record Mode'] = self._camera.record_mode
|
self._attrs['Record Mode'] = self._camera.record_mode
|
||||||
|
@ -8,8 +8,6 @@ from . import DATA_AMCREST, SWITCHES
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEPENDENCIES = ['amcrest']
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass, config, async_add_entities, discovery_info=None):
|
hass, config, async_add_entities, discovery_info=None):
|
||||||
|
1
homeassistant/components/ampio/__init__.py
Normal file
1
homeassistant/components/ampio/__init__.py
Normal file
@ -0,0 +1 @@
|
|||||||
|
"""The Ampio component."""
|
95
homeassistant/components/ampio/air_quality.py
Normal file
95
homeassistant/components/ampio/air_quality.py
Normal 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()
|
10
homeassistant/components/ampio/manifest.json
Normal file
10
homeassistant/components/ampio/manifest.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"domain": "ampio",
|
||||||
|
"name": "Ampio",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/ampio",
|
||||||
|
"requirements": [
|
||||||
|
"asmog==0.0.6"
|
||||||
|
],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
@ -21,8 +21,6 @@ from homeassistant.util.dt import utcnow
|
|||||||
from homeassistant.components.mjpeg.camera import (
|
from homeassistant.components.mjpeg.camera import (
|
||||||
CONF_MJPEG_URL, CONF_STILL_IMAGE_URL)
|
CONF_MJPEG_URL, CONF_STILL_IMAGE_URL)
|
||||||
|
|
||||||
REQUIREMENTS = ['pydroid-ipcam==0.8']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
ATTR_AUD_CONNS = 'Audio Connections'
|
ATTR_AUD_CONNS = 'Audio Connections'
|
||||||
|
@ -3,8 +3,6 @@ from homeassistant.components.binary_sensor import BinarySensorDevice
|
|||||||
|
|
||||||
from . import CONF_HOST, CONF_NAME, DATA_IP_WEBCAM, KEY_MAP, AndroidIPCamEntity
|
from . import CONF_HOST, CONF_NAME, DATA_IP_WEBCAM, KEY_MAP, AndroidIPCamEntity
|
||||||
|
|
||||||
DEPENDENCIES = ['android_ip_webcam']
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass, config, async_add_entities, discovery_info=None):
|
hass, config, async_add_entities, discovery_info=None):
|
||||||
|
10
homeassistant/components/android_ip_webcam/manifest.json
Normal file
10
homeassistant/components/android_ip_webcam/manifest.json
Normal 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": []
|
||||||
|
}
|
@ -5,8 +5,6 @@ from . import (
|
|||||||
CONF_HOST, CONF_NAME, CONF_SENSORS, DATA_IP_WEBCAM, ICON_MAP, KEY_MAP,
|
CONF_HOST, CONF_NAME, CONF_SENSORS, DATA_IP_WEBCAM, ICON_MAP, KEY_MAP,
|
||||||
AndroidIPCamEntity)
|
AndroidIPCamEntity)
|
||||||
|
|
||||||
DEPENDENCIES = ['android_ip_webcam']
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass, config, async_add_entities, discovery_info=None):
|
hass, config, async_add_entities, discovery_info=None):
|
||||||
|
@ -5,8 +5,6 @@ from . import (
|
|||||||
CONF_HOST, CONF_NAME, CONF_SWITCHES, DATA_IP_WEBCAM, ICON_MAP, KEY_MAP,
|
CONF_HOST, CONF_NAME, CONF_SWITCHES, DATA_IP_WEBCAM, ICON_MAP, KEY_MAP,
|
||||||
AndroidIPCamEntity)
|
AndroidIPCamEntity)
|
||||||
|
|
||||||
DEPENDENCIES = ['android_ip_webcam']
|
|
||||||
|
|
||||||
|
|
||||||
async def async_setup_platform(
|
async def async_setup_platform(
|
||||||
hass, config, async_add_entities, discovery_info=None):
|
hass, config, async_add_entities, discovery_info=None):
|
||||||
|
@ -1,6 +1 @@
|
|||||||
"""
|
"""Support for functionality to interact with Android TV/Fire TV devices."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
|
10
homeassistant/components/androidtv/manifest.json
Normal file
10
homeassistant/components/androidtv/manifest.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"domain": "androidtv",
|
||||||
|
"name": "Androidtv",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/androidtv",
|
||||||
|
"requirements": [
|
||||||
|
"androidtv==0.0.15"
|
||||||
|
],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Support for functionality to interact with Android TV / Fire TV devices."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
import functools
|
import functools
|
||||||
import logging
|
import logging
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -18,12 +13,11 @@ from homeassistant.const import (
|
|||||||
ATTR_COMMAND, ATTR_ENTITY_ID, CONF_DEVICE_CLASS, CONF_HOST, CONF_NAME,
|
ATTR_COMMAND, ATTR_ENTITY_ID, CONF_DEVICE_CLASS, CONF_HOST, CONF_NAME,
|
||||||
CONF_PORT, STATE_IDLE, STATE_OFF, STATE_PAUSED, STATE_PLAYING,
|
CONF_PORT, STATE_IDLE, STATE_OFF, STATE_PAUSED, STATE_PLAYING,
|
||||||
STATE_STANDBY)
|
STATE_STANDBY)
|
||||||
|
from homeassistant.exceptions import PlatformNotReady
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
ANDROIDTV_DOMAIN = 'androidtv'
|
ANDROIDTV_DOMAIN = 'androidtv'
|
||||||
|
|
||||||
REQUIREMENTS = ['androidtv==0.0.14']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
SUPPORT_ANDROIDTV = SUPPORT_PAUSE | SUPPORT_PLAY | \
|
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",
|
_LOGGER.warning("Could not connect to %s at %s%s",
|
||||||
device_name, host, adb_log)
|
device_name, host, adb_log)
|
||||||
return
|
raise PlatformNotReady
|
||||||
|
|
||||||
if host in hass.data[ANDROIDTV_DOMAIN]:
|
if host in hass.data[ANDROIDTV_DOMAIN]:
|
||||||
_LOGGER.warning("Platform already setup on %s, skipping", host)
|
_LOGGER.warning("Platform already setup on %s, skipping", host)
|
||||||
@ -298,12 +292,12 @@ class ADBDevice(MediaPlayerDevice):
|
|||||||
@adb_decorator()
|
@adb_decorator()
|
||||||
def media_previous_track(self):
|
def media_previous_track(self):
|
||||||
"""Send previous track command (results in rewind)."""
|
"""Send previous track command (results in rewind)."""
|
||||||
self.aftv.media_previous()
|
self.aftv.media_previous_track()
|
||||||
|
|
||||||
@adb_decorator()
|
@adb_decorator()
|
||||||
def media_next_track(self):
|
def media_next_track(self):
|
||||||
"""Send next track command (results in fast-forward)."""
|
"""Send next track command (results in fast-forward)."""
|
||||||
self.aftv.media_next()
|
self.aftv.media_next_track()
|
||||||
|
|
||||||
@adb_decorator()
|
@adb_decorator()
|
||||||
def adb_command(self, cmd):
|
def adb_command(self, cmd):
|
||||||
@ -328,11 +322,10 @@ class AndroidTVDevice(ADBDevice):
|
|||||||
turn_off_command)
|
turn_off_command)
|
||||||
|
|
||||||
self._device = None
|
self._device = None
|
||||||
self._muted = None
|
|
||||||
self._device_properties = self.aftv.device_properties
|
self._device_properties = self.aftv.device_properties
|
||||||
self._unique_id = 'androidtv-{}-{}'.format(
|
self._is_volume_muted = None
|
||||||
name, self._device_properties['serialno'])
|
self._unique_id = self._device_properties.get('serialno')
|
||||||
self._volume = None
|
self._volume_level = None
|
||||||
|
|
||||||
@adb_decorator(override_available=True)
|
@adb_decorator(override_available=True)
|
||||||
def update(self):
|
def update(self):
|
||||||
@ -349,16 +342,16 @@ class AndroidTVDevice(ADBDevice):
|
|||||||
if not self._available:
|
if not self._available:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Get the `state`, `current_app`, and `running_apps`.
|
# Get the updated state and attributes.
|
||||||
state, self._current_app, self._device, self._muted, self._volume = \
|
state, self._current_app, self._device, self._is_volume_muted, \
|
||||||
self.aftv.update()
|
self._volume_level = self.aftv.update()
|
||||||
|
|
||||||
self._state = ANDROIDTV_STATES[state]
|
self._state = ANDROIDTV_STATES[state]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_volume_muted(self):
|
def is_volume_muted(self):
|
||||||
"""Boolean if volume is currently muted."""
|
"""Boolean if volume is currently muted."""
|
||||||
return self._muted
|
return self._is_volume_muted
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def source(self):
|
def source(self):
|
||||||
@ -378,7 +371,7 @@ class AndroidTVDevice(ADBDevice):
|
|||||||
@property
|
@property
|
||||||
def volume_level(self):
|
def volume_level(self):
|
||||||
"""Return the volume level."""
|
"""Return the volume level."""
|
||||||
return self._volume
|
return self._volume_level
|
||||||
|
|
||||||
@adb_decorator()
|
@adb_decorator()
|
||||||
def media_stop(self):
|
def media_stop(self):
|
||||||
@ -393,12 +386,12 @@ class AndroidTVDevice(ADBDevice):
|
|||||||
@adb_decorator()
|
@adb_decorator()
|
||||||
def volume_down(self):
|
def volume_down(self):
|
||||||
"""Send volume down command."""
|
"""Send volume down command."""
|
||||||
self.aftv.volume_down()
|
self._volume_level = self.aftv.volume_down(self._volume_level)
|
||||||
|
|
||||||
@adb_decorator()
|
@adb_decorator()
|
||||||
def volume_up(self):
|
def volume_up(self):
|
||||||
"""Send volume up command."""
|
"""Send volume up command."""
|
||||||
self.aftv.volume_up()
|
self._volume_level = self.aftv.volume_up(self._volume_level)
|
||||||
|
|
||||||
|
|
||||||
class FireTVDevice(ADBDevice):
|
class FireTVDevice(ADBDevice):
|
||||||
|
10
homeassistant/components/anel_pwrctrl/manifest.json
Normal file
10
homeassistant/components/anel_pwrctrl/manifest.json
Normal 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": []
|
||||||
|
}
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Support for ANEL PwrCtrl switches."""
|
||||||
Support for ANEL PwrCtrl switches.
|
|
||||||
|
|
||||||
For more details about this platform, please refer to the documentation at
|
|
||||||
https://home-assistant.io/components/switch.pwrctrl/
|
|
||||||
"""
|
|
||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
from datetime import timedelta
|
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.const import (CONF_HOST, CONF_PASSWORD, CONF_USERNAME)
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
|
|
||||||
REQUIREMENTS = ['anel_pwrctrl-homeassistant==0.0.1.dev2']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_PORT_RECV = 'port_recv'
|
CONF_PORT_RECV = 'port_recv'
|
||||||
|
10
homeassistant/components/anthemav/manifest.json
Normal file
10
homeassistant/components/anthemav/manifest.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"domain": "anthemav",
|
||||||
|
"name": "Anthemav",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/anthemav",
|
||||||
|
"requirements": [
|
||||||
|
"anthemav==1.1.10"
|
||||||
|
],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""Support for Anthem Network Receivers and Processors."""
|
||||||
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/
|
|
||||||
"""
|
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
@ -18,8 +13,6 @@ from homeassistant.const import (
|
|||||||
STATE_ON)
|
STATE_ON)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
REQUIREMENTS = ['anthemav==1.1.10']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DOMAIN = 'anthemav'
|
DOMAIN = 'anthemav'
|
||||||
|
@ -8,8 +8,6 @@ from homeassistant.const import (CONF_HOST, CONF_PORT)
|
|||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
|
|
||||||
REQUIREMENTS = ['apcaccess==0.0.13']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
CONF_TYPE = 'type'
|
CONF_TYPE = 'type'
|
||||||
|
@ -8,8 +8,6 @@ import homeassistant.helpers.config_validation as cv
|
|||||||
from homeassistant.components import apcupsd
|
from homeassistant.components import apcupsd
|
||||||
|
|
||||||
DEFAULT_NAME = 'UPS Online Status'
|
DEFAULT_NAME = 'UPS Online Status'
|
||||||
DEPENDENCIES = [apcupsd.DOMAIN]
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||||
})
|
})
|
||||||
|
10
homeassistant/components/apcupsd/manifest.json
Normal file
10
homeassistant/components/apcupsd/manifest.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"domain": "apcupsd",
|
||||||
|
"name": "Apcupsd",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/apcupsd",
|
||||||
|
"requirements": [
|
||||||
|
"apcaccess==0.0.13"
|
||||||
|
],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
@ -11,8 +11,6 @@ from homeassistant.helpers.entity import Entity
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DEPENDENCIES = [apcupsd.DOMAIN]
|
|
||||||
|
|
||||||
SENSOR_PREFIX = 'UPS '
|
SENSOR_PREFIX = 'UPS '
|
||||||
SENSOR_TYPES = {
|
SENSOR_TYPES = {
|
||||||
'alarmdel': ['Alarm Delay', '', 'mdi:alarm'],
|
'alarmdel': ['Alarm Delay', '', 'mdi:alarm'],
|
||||||
|
@ -33,8 +33,6 @@ ATTR_REQUIRES_API_PASSWORD = 'requires_api_password'
|
|||||||
ATTR_VERSION = 'version'
|
ATTR_VERSION = 'version'
|
||||||
|
|
||||||
DOMAIN = 'api'
|
DOMAIN = 'api'
|
||||||
DEPENDENCIES = ['http']
|
|
||||||
|
|
||||||
STREAM_PING_PAYLOAD = 'ping'
|
STREAM_PING_PAYLOAD = 'ping'
|
||||||
STREAM_PING_INTERVAL = 50 # seconds
|
STREAM_PING_INTERVAL = 50 # seconds
|
||||||
|
|
||||||
|
12
homeassistant/components/api/manifest.json
Normal file
12
homeassistant/components/api/manifest.json
Normal 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"
|
||||||
|
]
|
||||||
|
}
|
0
homeassistant/components/api/services.yaml
Normal file
0
homeassistant/components/api/services.yaml
Normal file
@ -1 +0,0 @@
|
|||||||
"""The api_streams component."""
|
|
10
homeassistant/components/apns/manifest.json
Normal file
10
homeassistant/components/apns/manifest.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"domain": "apns",
|
||||||
|
"name": "Apns",
|
||||||
|
"documentation": "https://www.home-assistant.io/components/apns",
|
||||||
|
"requirements": [
|
||||||
|
"apns2==0.3.0"
|
||||||
|
],
|
||||||
|
"dependencies": [],
|
||||||
|
"codeowners": []
|
||||||
|
}
|
@ -1,9 +1,4 @@
|
|||||||
"""
|
"""APNS Notification platform."""
|
||||||
APNS Notification platform.
|
|
||||||
|
|
||||||
For more details about this platform, please refer to the documentation at
|
|
||||||
https://home-assistant.io/components/notify.apns/
|
|
||||||
"""
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
|
||||||
@ -18,8 +13,6 @@ from homeassistant.helpers.event import track_state_change
|
|||||||
from homeassistant.components.notify import (
|
from homeassistant.components.notify import (
|
||||||
ATTR_DATA, ATTR_TARGET, DOMAIN, PLATFORM_SCHEMA, BaseNotificationService)
|
ATTR_DATA, ATTR_TARGET, DOMAIN, PLATFORM_SCHEMA, BaseNotificationService)
|
||||||
|
|
||||||
REQUIREMENTS = ['apns2==0.3.0']
|
|
||||||
|
|
||||||
APNS_DEVICES = 'apns.yaml'
|
APNS_DEVICES = 'apns.yaml'
|
||||||
CONF_CERTFILE = 'cert_file'
|
CONF_CERTFILE = 'cert_file'
|
||||||
CONF_TOPIC = 'topic'
|
CONF_TOPIC = 'topic'
|
||||||
|
0
homeassistant/components/apns/services.yaml
Normal file
0
homeassistant/components/apns/services.yaml
Normal file
@ -11,8 +11,6 @@ from homeassistant.helpers import discovery
|
|||||||
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
REQUIREMENTS = ['pyatv==0.3.12']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
DOMAIN = 'apple_tv'
|
DOMAIN = 'apple_tv'
|
||||||
|
10
homeassistant/components/apple_tv/manifest.json
Normal file
10
homeassistant/components/apple_tv/manifest.json
Normal 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": []
|
||||||
|
}
|
@ -14,8 +14,6 @@ import homeassistant.util.dt as dt_util
|
|||||||
|
|
||||||
from . import ATTR_ATV, ATTR_POWER, DATA_APPLE_TV, DATA_ENTITIES
|
from . import ATTR_ATV, ATTR_POWER, DATA_APPLE_TV, DATA_ENTITIES
|
||||||
|
|
||||||
DEPENDENCIES = ['apple_tv']
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
SUPPORT_APPLE_TV = SUPPORT_TURN_ON | SUPPORT_TURN_OFF | SUPPORT_PLAY_MEDIA | \
|
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
Loading…
x
Reference in New Issue
Block a user