From 974b29ebac76e365aa99fc211609bb8a1ba71f71 Mon Sep 17 00:00:00 2001 From: Tom Brien Date: Wed, 19 Feb 2020 19:36:13 +0000 Subject: [PATCH] =?UTF-8?q?Migrate=20to=20Docusaurus=20V2=20=F0=9F=90=B1?= =?UTF-8?q?=E2=80=8D=F0=9F=90=89=20(#412)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Migrate to Docusaurus V2 * Add redirects Only covers most recent version * Add omitted scripts folder * Include working yarn.lock --- .gitignore | 30 +- .nvmrc | 2 +- .../2018-05-22-custom-ui-panels-api.md | 0 .../2018-06-01-071-custom-panels.md | 2 +- .../2018-07-02-trying-new-auth.md | 0 .../2018-08-13-deprecating-remote-package.md | 0 .../2019-02-19-the-great-migration.md | 0 .../2019-03-11-user-permissions.md | 0 .../2019-04-12-new-integration-structure.md | 0 ...2-internet-of-things-and-the-modern-web.md | 41 +- .../2019-07-03-climate-cleanup.md | 15 +- .../2019-07-19-building-all-the-things.md | 19 +- {website/blog => blog}/2019-07-31-black.md | 0 .../blog => blog}/2019-09-27-hacktoberfest.md | 16 +- .../blog => blog}/2019-10-05-simple-mode.md | 13 +- .../blog => blog}/2020-02-04-new-zwave.md | 13 +- crowdin.yaml | 53 - docs/architecture_components.md | 6 +- docs/architecture_entities.md | 4 +- docs/architecture_hassio.md | 3 +- docs/architecture_index.md | 4 +- docs/auth_api.md | 5 +- docs/auth_auth_module.md | 3 +- docs/auth_index.md | 3 +- docs/config_entries_index.md | 4 +- docs/creating_platform_code_review.md | 2 +- docs/dev_101_hass.md | 6 +- docs/dev_101_index.md | 2 +- docs/device_registry_index.md | 2 +- docs/entity_media_player.md | 1 + docs/external_api_rest.md | 8 +- docs/intent_index.md | 2 +- docs/internationalization_translation.md | 2 +- docusaurus.config.js | 74 + netlify.toml | 19 + package.json | 30 + script/bootstrap | 1 - script/netlify | 15 +- script/server | 1 - script/setup | 0 website/sidebars.json => sidebars.js | 13 +- src/css/custom.css | 102 + src/pages/index.js | 171 + src/pages/styles.module.css | 35 + .../static => static}/img/default-social.png | Bin .../img/dev-tools/about-icon.png | Bin .../img/dev-tools/events-icon.png | Bin .../img/dev-tools/mqtt-icon.png | Bin .../img/dev-tools/services-icon.png | Bin .../img/dev-tools/states-icon.png | Bin .../img/dev-tools/templates-icon.png | Bin {website/static => static}/img/docusaurus.svg | 0 .../en/architecture/component_interaction.png | Bin .../en/architecture/entities_architecture.png | Bin .../img/en/architecture/ha_architecture.svg | 0 .../en/architecture/ha_full_architecture.png | Bin static/img/en/architecture/hassio.png | Bin 0 -> 21821 bytes .../home_automation_landscape.svg | 0 .../img/en/auth/architecture.png | Bin .../img/en/auth/authorize_flow.png | Bin .../img/en/auth/mfa_workflow.png | Bin .../en/blog/2018-07-experimental-auth/cli.png | Bin .../2019-03-user-permissions/screenshot.png | Bin .../build-cabinet.jpg | Bin .../local-hosted-agent.png | Bin .../social.png | Bin .../test-results.png | Bin .../test-stages.png | Bin .../2019-10-simple-mode/config-concepts.png | Bin .../img/en/development/bypass-for-network.png | Bin .../img/en/development/create-component01.png | Bin .../img/en/development/disable-cache.png | Bin .../img/en/device_registry/overview.png | Bin .../img/en/frontend/frontend-badges.png | Bin .../img/en/frontend/frontend-cards1.png | Bin static/img/en/frontend/frontend-hero.png | Bin 0 -> 380561 bytes .../en/frontend/frontend-more-info-light.png | Bin .../en/frontend/hello-world-state-card.png | Bin .../en/frontend/lovelace-ui-comparison.png | Bin .../lovelace-ui-custom-card-screenshot.png | Bin .../screenshots/adding_repositories.png | Bin .../screenshots/addon-hass-configurator.png | Bin .../img/en/hass.io/screenshots/dashboard.png | Bin .../en/hass.io/screenshots/first-start.png | Bin .../hass.io/screenshots/local_repository.png | Bin .../screenshots/main_panel_addon_store.png | Bin .../en/hass.io/screenshots/ssh-upgrade.png | Bin .../tutorial/addon_hello_world_logs.png | Bin .../hass.io/tutorial/python3-http-server.png | Bin .../img/en/hass.io/tutorial/samba.png | Bin .../img/en/hass.io/tutorial/ssh.png | Bin .../img/en/intents/overview.png | Bin static/img/favicon.ico | Bin 0 -> 766 bytes {website/static => static}/img/favicon.png | Bin .../static => static}/img/favicon/favicon.ico | Bin static/img/logo-pretty.svg | 46 + .../static => static}/img/logo-responsive.svg | 0 {website/static => static}/img/logo-white.svg | 0 static/img/logo.svg | 1 + .../static => static}/img/profile/paulus.jpg | Bin static/img/undraw_docusaurus_mountain.svg | 170 + static/img/undraw_docusaurus_react.svg | 169 + static/img/undraw_docusaurus_tree.svg | 1 + static/js/discourse_discussion.jsx | 112 + website/core/Footer.js | 93 - website/i18n/en.json | 2104 ---- website/i18n/no-NO.json | 1529 --- website/languages.js | 181 - website/package.json | 17 - website/pages/en/help-with-translations.js | 70 - website/pages/en/help.js | 57 - website/pages/en/index.js | 272 - website/pages/en/users.js | 49 - website/pages/en/versions.js | 95 - website/siteConfig.js | 111 - website/static/css/custom.css | 52 - website/static/img/en/architecture/hassio.png | Bin 10438 -> 0 bytes .../static/img/en/frontend/frontend-hero.png | Bin 231797 -> 0 bytes .../version-0.74.0/lovelace_custom_card.md | 212 - .../version-0.78.0/frontend_add_more_info.md | 15 - .../version-0.78.0/frontend_external_auth.md | 68 - .../hassio_addon_communication.md | 37 - .../version-0.78.0/hassio_addon_config.md | 207 - .../version-0.78.0/hassio_addon_security.md | 33 - .../creating_component_code_review.md | 49 - .../creating_platform_code_review.md | 82 - .../version-0.79.0/development_environment.md | 113 - .../documentation_create_page.md | 134 - .../version-0.79.0/documentation_index.md | 37 - .../hassio_addon_communication.md | 37 - .../ko-KR/version-0.79.0/hassio_hass.md | 54 - .../version-0.86.0/hassio_addon_config.md | 212 - .../version-0.87.0/area_registry_index.md | 13 - .../creating_component_code_review.md | 71 - .../creating_component_deps_and_reqs.md | 9 - .../creating_component_generic_discovery.md | 22 - .../creating_component_index.md | 40 - .../creating_integration_file_structure.md | 33 - .../creating_integration_manifest.md | 79 - .../creating_platform_code_review.md | 95 - .../creating_platform_example_light.md | 9 - .../creating_platform_example_sensor.md | 9 - .../version-0.91.2/creating_platform_index.md | 23 - .../ko-KR/version-0.91.2/dev_101_services.md | 78 - .../ko-KR/version-0.91.2/dev_101_states.md | 128 - .../version-0.91.2/development_checklist.md | 17 - .../version-0.91.2/development_guidelines.md | 83 - .../ko-KR/version-0.91.2/development_index.md | 12 - .../version-0.91.2/development_validation.md | 82 - .../ko-KR/version-0.91.2/entity_sensor.md | 33 - .../internationalization_translation.md | 44 - .../ko-KR/version-0.91.2/maintenance.md | 45 - .../version-0.92.0/app_integration_setup.md | 82 - .../ko-KR/version-0.92.0/auth_auth_module.md | 68 - .../creating_integration_manifest.md | 79 - .../version-0.92.0/creating_platform_index.md | 23 - .../version-0.92.0/development_submitting.md | 43 - .../ko-KR/version-0.92.0/entity_climate.md | 232 - .../ko-KR/version-0.92.0/entity_fan.md | 89 - .../version-0.92.0/entity_registry_index.md | 24 - .../ko/app_integration_notifications.md | 235 - .../nl/app_integration_index.md | 11 - .../nl/app_integration_notifications.md | 235 - .../nl/app_integration_sending_data.md | 228 - .../nl/app_integration_sensors.md | 77 - .../nl/app_integration_setup.md | 80 - .../nl/app_integration_webview.md | 9 - .../nl/architecture_components.md | 50 - .../nl/architecture_entities.md | 41 - .../translated_docs/nl/architecture_hassio.md | 26 - .../translated_docs/nl/architecture_index.md | 23 - .../translated_docs/nl/area_registry_index.md | 11 - website/translated_docs/nl/asyncio_101.md | 9 - .../nl/asyncio_categorizing_functions.md | 67 - website/translated_docs/nl/asyncio_index.md | 16 - .../nl/asyncio_working_with_async.md | 102 - website/translated_docs/nl/auth_api.md | 245 - .../translated_docs/nl/auth_auth_module.md | 66 - .../translated_docs/nl/auth_auth_provider.md | 42 - website/translated_docs/nl/auth_index.md | 50 - .../translated_docs/nl/auth_permissions.md | 266 - .../nl/config_entries_config_flow_handler.md | 91 - .../nl/config_entries_index.md | 166 - .../nl/config_entries_options_flow_handler.md | 44 - .../nl/configuration_yaml_index.md | 57 - .../nl/creating_component_code_review.md | 69 - .../nl/creating_component_deps_and_reqs.md | 7 - .../creating_component_generic_discovery.md | 20 - .../nl/creating_component_index.md | 38 - .../nl/creating_integration_file_structure.md | 31 - .../nl/creating_integration_manifest.md | 77 - .../nl/creating_platform_code_review.md | 93 - .../nl/creating_platform_example_light.md | 7 - .../nl/creating_platform_example_sensor.md | 7 - .../nl/creating_platform_index.md | 21 - .../nl/data_entry_flow_index.md | 223 - website/translated_docs/nl/dev_101_config.md | 28 - website/translated_docs/nl/dev_101_events.md | 58 - website/translated_docs/nl/dev_101_hass.md | 30 - website/translated_docs/nl/dev_101_index.md | 44 - .../translated_docs/nl/dev_101_services.md | 76 - website/translated_docs/nl/dev_101_states.md | 126 - .../nl/development_catching_up.md | 35 - .../nl/development_checklist.md | 14 - .../nl/development_environment.md | 117 - .../nl/development_guidelines.md | 81 - .../translated_docs/nl/development_index.md | 10 - .../nl/development_submitting.md | 41 - .../translated_docs/nl/development_testing.md | 79 - .../translated_docs/nl/development_typing.md | 23 - .../nl/development_validation.md | 80 - .../nl/device_registry_index.md | 80 - .../nl/documentation_create_page.md | 132 - .../translated_docs/nl/documentation_index.md | 52 - .../nl/documentation_standards.md | 122 - .../translated_docs/nl/entity_air_quality.md | 25 - .../nl/entity_alarm_control_panel.md | 130 - .../nl/entity_binary_sensor.md | 43 - website/translated_docs/nl/entity_climate.md | 230 - website/translated_docs/nl/entity_cover.md | 188 - website/translated_docs/nl/entity_fan.md | 87 - website/translated_docs/nl/entity_index.md | 102 - website/translated_docs/nl/entity_light.md | 61 - website/translated_docs/nl/entity_lock.md | 16 - .../translated_docs/nl/entity_media_player.md | 84 - .../nl/entity_registry_index.md | 22 - website/translated_docs/nl/entity_remote.md | 16 - website/translated_docs/nl/entity_sensor.md | 31 - website/translated_docs/nl/entity_switch.md | 72 - website/translated_docs/nl/entity_vacuum.md | 63 - .../translated_docs/nl/entity_water_heater.md | 51 - website/translated_docs/nl/entity_weather.md | 55 - .../translated_docs/nl/external_api_rest.md | 530 - .../nl/external_api_rest_python.md | 7 - .../nl/external_api_server_sent_events.md | 72 - .../nl/external_api_websocket.md | 434 - .../translated_docs/nl/frontend_add_card.md | 21 - .../nl/frontend_add_more_info.md | 13 - .../no-NO/app_integration_notifications.md | 235 - .../no-NO/app_integration_sensors.md | 77 - .../no-NO/app_integration_setup.md | 80 - .../no-NO/app_integration_webview.md | 9 - .../no-NO/architecture_components.md | 50 - .../no-NO/architecture_entities.md | 41 - .../no-NO/architecture_hassio.md | 26 - .../no-NO/architecture_index.md | 23 - .../no-NO/area_registry_index.md | 11 - website/translated_docs/no-NO/asyncio_101.md | 9 - .../no-NO/asyncio_categorizing_functions.md | 67 - .../translated_docs/no-NO/asyncio_index.md | 16 - .../no-NO/asyncio_working_with_async.md | 102 - website/translated_docs/no-NO/auth_api.md | 245 - .../translated_docs/no-NO/auth_auth_module.md | 66 - .../no-NO/auth_auth_provider.md | 42 - website/translated_docs/no-NO/auth_index.md | 50 - .../translated_docs/no-NO/auth_permissions.md | 266 - .../config_entries_config_flow_handler.md | 91 - .../no-NO/config_entries_index.md | 166 - .../no-NO/creating_component_index.md | 38 - .../creating_integration_file_structure.md | 31 - .../no-NO/creating_integration_manifest.md | 77 - .../no-NO/creating_platform_code_review.md | 93 - .../no-NO/creating_platform_example_light.md | 7 - .../no-NO/creating_platform_example_sensor.md | 7 - .../no-NO/creating_platform_index.md | 21 - .../no-NO/data_entry_flow_index.md | 223 - .../translated_docs/no-NO/dev_101_config.md | 28 - .../translated_docs/no-NO/dev_101_events.md | 58 - website/translated_docs/no-NO/dev_101_hass.md | 30 - .../translated_docs/no-NO/dev_101_index.md | 44 - .../translated_docs/no-NO/dev_101_services.md | 76 - .../translated_docs/no-NO/dev_101_states.md | 126 - .../no-NO/development_catching_up.md | 35 - .../no-NO/development_checklist.md | 14 - .../no-NO/development_environment.md | 117 - .../no-NO/development_guidelines.md | 81 - .../no-NO/development_index.md | 10 - .../no-NO/development_submitting.md | 41 - .../no-NO/development_testing.md | 79 - .../no-NO/development_typing.md | 23 - .../no-NO/development_validation.md | 80 - .../no-NO/device_registry_index.md | 80 - .../no-NO/documentation_create_page.md | 132 - .../no-NO/documentation_index.md | 52 - .../no-NO/documentation_standards.md | 122 - .../no-NO/entity_air_quality.md | 25 - .../no-NO/entity_alarm_control_panel.md | 130 - .../no-NO/entity_binary_sensor.md | 43 - .../translated_docs/no-NO/entity_climate.md | 230 - website/translated_docs/no-NO/entity_cover.md | 188 - website/translated_docs/no-NO/entity_fan.md | 87 - website/translated_docs/no-NO/entity_index.md | 102 - website/translated_docs/no-NO/entity_light.md | 61 - website/translated_docs/no-NO/entity_lock.md | 16 - .../no-NO/entity_media_player.md | 84 - .../no-NO/entity_registry_index.md | 22 - .../translated_docs/no-NO/entity_remote.md | 16 - .../translated_docs/no-NO/entity_sensor.md | 31 - .../translated_docs/no-NO/entity_switch.md | 72 - .../translated_docs/no-NO/entity_vacuum.md | 63 - .../no-NO/entity_water_heater.md | 51 - .../translated_docs/no-NO/entity_weather.md | 55 - .../no-NO/external_api_rest.md | 530 - .../no-NO/external_api_rest_python.md | 7 - .../no-NO/external_api_server_sent_events.md | 72 - .../no-NO/external_api_websocket.md | 434 - .../no-NO/frontend_add_card.md | 21 - .../no-NO/frontend_add_more_info.md | 13 - .../no-NO/frontend_add_websocket_api.md | 129 - .../no-NO/frontend_architecture.md | 60 - .../no-NO/frontend_creating_custom_panels.md | 42 - .../no-NO/frontend_creating_custom_ui.md | 118 - .../translated_docs/no-NO/frontend_data.md | 137 - .../no-NO/frontend_development.md | 103 - .../no-NO/frontend_external_auth.md | 66 - .../translated_docs/no-NO/frontend_index.md | 10 - .../no-NO/hassio_addon_communication.md | 39 - .../no-NO/hassio_addon_config.md | 222 - .../no-NO/hassio_addon_index.md | 28 - .../no-NO/hassio_addon_presentation.md | 63 - .../no-NO/hassio_addon_publishing.md | 56 - .../no-NO/hassio_addon_repository.md | 29 - .../no-NO/hassio_addon_security.md | 38 - .../no-NO/hassio_addon_testing.md | 28 - .../no-NO/hassio_addon_tutorial.md | 179 - .../translated_docs/no-NO/hassio_debugging.md | 82 - website/translated_docs/no-NO/hassio_hass.md | 58 - .../no-NO/integration_quality_scale_index.md | 54 - .../translated_docs/no-NO/intent_builtin.md | 77 - .../no-NO/intent_conversation.md | 19 - .../translated_docs/no-NO/intent_firing.md | 52 - .../translated_docs/no-NO/intent_handling.md | 42 - website/translated_docs/no-NO/intent_index.md | 33 - ...ternationalization_backend_localization.md | 46 - ...alization_custom_component_localization.md | 13 - .../no-NO/internationalization_index.md | 11 - .../no-NO/internationalization_translation.md | 42 - .../no-NO/lovelace_custom_card.md | 225 - .../translated_docs/no-NO/lovelace_index.md | 8 - website/translated_docs/no-NO/maintenance.md | 43 - website/translated_docs/no-NO/misc.md | 5 - website/translated_docs/no-NO/releasing.md | 67 - .../pl/app_integration_index.md | 11 - .../pl/app_integration_notifications.md | 235 - .../pl/app_integration_sending_data.md | 228 - .../pl/app_integration_sensors.md | 77 - .../pl/app_integration_setup.md | 80 - .../pl/app_integration_webview.md | 9 - .../pl/architecture_components.md | 50 - .../pl/architecture_entities.md | 41 - .../translated_docs/pl/architecture_hassio.md | 26 - .../translated_docs/pl/architecture_index.md | 23 - .../translated_docs/pl/area_registry_index.md | 11 - website/translated_docs/pl/asyncio_101.md | 9 - .../pl/asyncio_categorizing_functions.md | 67 - website/translated_docs/pl/asyncio_index.md | 16 - .../pl/asyncio_working_with_async.md | 102 - website/translated_docs/pl/auth_api.md | 245 - .../translated_docs/pl/auth_auth_module.md | 66 - .../translated_docs/pl/auth_auth_provider.md | 42 - website/translated_docs/pl/auth_index.md | 50 - .../translated_docs/pl/auth_permissions.md | 266 - .../pl/config_entries_config_flow_handler.md | 91 - .../pl/config_entries_index.md | 166 - .../pl/config_entries_options_flow_handler.md | 44 - .../pl/configuration_yaml_index.md | 57 - .../pl/creating_component_code_review.md | 69 - .../pl/creating_component_deps_and_reqs.md | 7 - .../creating_component_generic_discovery.md | 20 - .../pl/creating_component_index.md | 38 - .../pl/creating_integration_file_structure.md | 31 - .../pl/creating_integration_manifest.md | 77 - .../pl/creating_platform_code_review.md | 93 - .../pl/creating_platform_example_light.md | 7 - .../pl/creating_platform_example_sensor.md | 7 - .../pl/creating_platform_index.md | 21 - .../pl/data_entry_flow_index.md | 223 - website/translated_docs/pl/dev_101_config.md | 28 - website/translated_docs/pl/dev_101_events.md | 58 - website/translated_docs/pl/dev_101_hass.md | 30 - website/translated_docs/pl/dev_101_index.md | 44 - .../translated_docs/pl/dev_101_services.md | 76 - website/translated_docs/pl/dev_101_states.md | 126 - .../pl/development_catching_up.md | 35 - .../pl/development_checklist.md | 14 - .../pl/development_environment.md | 117 - .../pl/development_guidelines.md | 81 - .../translated_docs/pl/development_index.md | 10 - .../pl/development_submitting.md | 41 - .../translated_docs/pl/development_testing.md | 79 - .../translated_docs/pl/development_typing.md | 23 - .../pl/development_validation.md | 80 - .../pl/device_registry_index.md | 80 - .../pl/documentation_create_page.md | 132 - .../translated_docs/pl/documentation_index.md | 52 - .../pl/documentation_standards.md | 122 - .../translated_docs/pl/entity_air_quality.md | 25 - .../pl/entity_alarm_control_panel.md | 130 - .../pl/entity_binary_sensor.md | 43 - website/translated_docs/pl/entity_climate.md | 230 - website/translated_docs/pl/entity_cover.md | 188 - website/translated_docs/pl/entity_fan.md | 87 - website/translated_docs/pl/entity_index.md | 102 - website/translated_docs/pl/entity_light.md | 61 - website/translated_docs/pl/entity_lock.md | 16 - .../translated_docs/pl/entity_media_player.md | 84 - .../pl/entity_registry_index.md | 22 - website/translated_docs/pl/entity_remote.md | 16 - website/translated_docs/pl/entity_sensor.md | 31 - website/translated_docs/pl/entity_switch.md | 72 - website/translated_docs/pl/entity_vacuum.md | 63 - .../translated_docs/pl/entity_water_heater.md | 51 - website/translated_docs/pl/entity_weather.md | 55 - .../translated_docs/pl/external_api_rest.md | 530 - .../pl/external_api_rest_python.md | 7 - .../pl/external_api_server_sent_events.md | 72 - .../pl/external_api_websocket.md | 434 - .../translated_docs/pl/frontend_add_card.md | 21 - .../creating_component_index.md | 45 - .../creating_platform_code_review.md | 88 - .../development_environment.md | 149 - .../version-0.100.0/external_api_rest.md | 552 - .../version-0.100.0/hassio_hass.md | 59 - .../version-0.101.0/api_lib_auth.md | 265 - .../version-0.101.0/api_lib_data_models.md | 148 - .../version-0.101.0/api_lib_index.md | 46 - .../config_entries_config_flow_handler.md | 120 - .../config_entries_options_flow_handler.md | 60 - .../version-0.101.0/data_entry_flow_index.md | 288 - .../documentation_create_page.md | 137 - .../version-0.101.0/documentation_index.md | 54 - .../documentation_standards.md | 123 - .../version-0.101.0/entity_climate.md | 221 - .../version-0.101.0/hassio_addon_config.md | 232 - .../integration_quality_scale_index.md | 56 - .../version-0.101.0/lovelace_custom_card.md | 243 - .../version-0.102.0/app_integration_setup.md | 87 - .../config_entries_config_flow_handler.md | 120 - .../version-0.102.0/development_testing.md | 86 - .../version-0.102.0/entity_index.md | 113 - .../version-0.102.0/frontend_external_auth.md | 68 - .../hassio_addon_communication.md | 48 - .../version-0.102.0/lovelace_custom_card.md | 249 - .../version-0.103.0/api_lib_auth.md | 267 - .../app_integration_sending_data.md | 230 - .../config_entries_config_flow_handler.md | 122 - .../creating_integration_manifest.md | 135 - .../version-0.103.0/development_testing.md | 86 - .../version-0.103.0/external_api_rest.md | 552 - .../version-0.103.0/hassio_addon_config.md | 232 - .../internationalization_translation.md | 43 - .../version-0.103.0/maintenance.md | 47 - .../version-0.104.0/api_lib_auth.md | 257 - .../version-0.104.0/api_lib_data_models.md | 145 - .../version-0.104.0/api_lib_index.md | 46 - .../version-0.104.0/app_integration_setup.md | 89 - .../asyncio_categorizing_functions.md | 71 - .../asyncio_working_with_async.md | 114 - .../version-0.104.0/auth_api.md | 257 - .../version-0.104.0/auth_auth_provider.md | 48 - .../version-0.104.0/auth_permissions.md | 278 - .../config_entries_config_flow_handler.md | 147 - .../version-0.104.0/config_entries_index.md | 140 - .../config_entries_options_flow_handler.md | 60 - .../configuration_yaml_index.md | 57 - .../creating_component_code_review.md | 69 - .../creating_component_index.md | 47 - .../creating_integration_manifest.md | 150 - .../creating_platform_code_review.md | 90 - .../version-0.104.0/data_entry_flow_index.md | 279 - .../version-0.104.0/dev_101_config.md | 30 - .../version-0.104.0/dev_101_events.md | 63 - .../version-0.104.0/dev_101_index.md | 49 - .../version-0.104.0/dev_101_services.md | 78 - .../version-0.104.0/dev_101_states.md | 130 - .../development_catching_up.md | 38 - .../development_environment.md | 151 - .../version-0.104.0/development_guidelines.md | 71 - .../version-0.104.0/development_testing.md | 86 - .../version-0.104.0/development_validation.md | 95 - .../version-0.104.0/device_registry_index.md | 81 - .../documentation_create_page.md | 142 - .../version-0.104.0/documentation_index.md | 54 - .../version-0.104.0/entity_cover.md | 188 - .../version-0.104.0/entity_fan.md | 98 - .../version-0.104.0/entity_index.md | 113 - .../version-0.104.0/entity_light.md | 60 - .../version-0.104.0/entity_media_player.md | 77 - .../version-0.104.0/entity_switch.md | 71 - .../version-0.104.0/external_api_rest.md | 552 - .../external_api_server_sent_events.md | 74 - .../frontend_add_websocket_api.md | 145 - .../frontend_creating_custom_ui.md | 122 - .../version-0.104.0/frontend_development.md | 105 - .../version-0.104.0/frontend_external_auth.md | 72 - .../version-0.104.0/hassio_addon_config.md | 232 - .../hassio_addon_publishing.md | 60 - .../version-0.104.0/hassio_addon_tutorial.md | 182 - .../version-0.104.0/hassio_debugging.md | 91 - .../version-0.104.0/hassio_hass.md | 59 - .../version-0.104.0/intent_conversation.md | 21 - .../version-0.104.0/intent_firing.md | 52 - .../version-0.104.0/intent_handling.md | 45 - ...ternationalization_backend_localization.md | 45 - .../internationalization_translation.md | 43 - .../version-0.104.0/lovelace_custom_card.md | 249 - .../version-0.104.0/maintenance.md | 47 - .../version-0.104.0/reproduce_state_index.md | 29 - .../app_integration_notifications.md | 239 - .../app_integration_sensors.md | 80 - .../version-0.105.0/dev_101_services.md | 109 - .../device_automation_condition.md | 29 - .../documentation_standards.md | 123 - .../version-0.105.0/entity_cover.md | 188 - .../version-0.105.0/entity_index.md | 114 - .../version-0.105.0/entity_lock.md | 66 - .../entity_registry_disabled_by.md | 42 - .../version-0.105.0/external_api_rest.md | 554 - .../version-0.105.0/frontend_data.md | 140 - .../version-0.105.0/hassio_addon_config.md | 237 - .../hassio_addon_presentation.md | 66 - .../integration_fetching_data.md | 154 - .../integration_quality_scale_index.md | 59 - .../version-0.72/architecture_components.md | 55 - .../version-0.72/architecture_entities.md | 43 - .../version-0.72/architecture_hassio.md | 31 - .../version-0.72/architecture_index.md | 31 - .../version-0.72/asyncio_101.md | 13 - .../asyncio_categorizing_functions.md | 69 - .../version-0.72/asyncio_index.md | 21 - .../asyncio_working_with_async.md | 112 - .../versioned_docs/version-0.72/auth_api.md | 90 - .../version-0.72/auth_auth_provider.md | 26 - .../versioned_docs/version-0.72/auth_index.md | 42 - .../config_entries_config_flow_handler.md | 80 - .../version-0.72/config_entries_index.md | 39 - .../version-0.72/configuration_yaml_index.md | 58 - .../creating_component_code_review.md | 29 - .../creating_component_deps_and_reqs.md | 51 - .../creating_component_discovery.md | 53 - .../version-0.72/creating_component_events.md | 7 - .../creating_component_generic_discovery.md | 72 - .../version-0.72/creating_component_index.md | 21 - .../creating_component_loading.md | 16 - .../version-0.72/creating_component_states.md | 17 - .../creating_platform_code_review.md | 72 - .../creating_platform_example_light.md | 119 - .../creating_platform_example_sensor.md | 61 - .../version-0.72/creating_platform_index.md | 31 - .../version-0.72/data_entry_flow_index.md | 190 - .../version-0.72/dev_101_config.md | 30 - .../version-0.72/dev_101_events.md | 57 - .../version-0.72/dev_101_hass.md | 32 - .../version-0.72/dev_101_index.md | 49 - .../version-0.72/dev_101_services.md | 50 - .../version-0.72/dev_101_states.md | 133 - .../version-0.72/development_catching_up.md | 36 - .../version-0.72/development_checklist.md | 15 - .../version-0.72/development_environment.md | 104 - .../version-0.72/development_guidelines.md | 76 - .../version-0.72/development_index.md | 27 - .../version-0.72/development_submitting.md | 42 - .../version-0.72/development_testing.md | 71 - .../version-0.72/development_typing.md | 25 - .../version-0.72/development_validation.md | 82 - .../entity_alarm_control_panel.md | 27 - .../version-0.72/entity_binary_sensor.md | 45 - .../version-0.72/entity_climate.md | 18 - .../version-0.72/entity_cover.md | 18 - .../versioned_docs/version-0.72/entity_fan.md | 18 - .../version-0.72/entity_index.md | 104 - .../version-0.72/entity_light.md | 18 - .../version-0.72/entity_lock.md | 18 - .../version-0.72/entity_media_player.md | 31 - .../version-0.72/entity_registry_index.md | 24 - .../version-0.72/entity_remote.md | 18 - .../version-0.72/entity_sensor.md | 29 - .../version-0.72/entity_switch.md | 65 - .../version-0.72/entity_vacuum.md | 18 - .../version-0.72/entity_weather.md | 57 - .../version-0.72/external_api_rest.md | 517 - .../version-0.72/external_api_rest_python.md | 231 - .../external_api_server_sent_events.md | 68 - .../version-0.72/external_api_websocket.md | 418 - .../version-0.72/frontend_add_card.md | 23 - .../version-0.72/frontend_add_more_info.md | 18 - .../frontend_add_websocket_api.md | 131 - .../version-0.72/frontend_architecture.md | 64 - .../frontend_creating_custom_panels.md | 84 - .../frontend_creating_custom_ui.md | 120 - .../version-0.72/frontend_development.md | 88 - .../version-0.72/frontend_index.md | 12 - .../hassio_addon_communication.md | 35 - .../version-0.72/hassio_addon_config.md | 202 - .../version-0.72/hassio_addon_index.md | 18 - .../version-0.72/hassio_addon_presentation.md | 48 - .../version-0.72/hassio_addon_publishing.md | 57 - .../version-0.72/hassio_addon_repository.md | 31 - .../version-0.72/hassio_addon_testing.md | 31 - .../version-0.72/hassio_addon_tutorial.md | 179 - .../version-0.72/hassio_debugging.md | 45 - .../version-0.72/hassio_hass.md | 80 - .../version-0.72/intent_builtin.md | 79 - .../version-0.72/intent_conversation.md | 21 - .../version-0.72/intent_firing.md | 54 - .../version-0.72/intent_handling.md | 44 - .../version-0.72/intent_index.md | 36 - ...ternationalization_backend_localization.md | 45 - ...alization_custom_component_localization.md | 14 - .../internationalization_index.md | 13 - .../internationalization_translation.md | 42 - .../version-0.72/lovelace_card_types.md | 110 - .../version-0.72/lovelace_custom_card.md | 168 - .../version-0.72/lovelace_index.md | 101 - .../version-0.72/maintenance.md | 47 - website/versioned_docs/version-0.72/misc.md | 7 - .../versioned_docs/version-0.72/releasing.md | 69 - .../versioned_docs/version-0.73.0/auth_api.md | 89 - .../version-0.73.0/development_guidelines.md | 85 - .../documentation_create_page.md | 122 - .../version-0.73.0/documentation_index.md | 38 - .../version-0.73.0/documentation_standards.md | 112 - .../version-0.73.0/frontend_development.md | 104 - .../version-0.73.0/hassio_addon_config.md | 202 - .../version-0.73.0/lovelace_custom_card.md | 211 - .../version-0.73.0/lovelace_index.md | 10 - .../asyncio_working_with_async.md | 108 - .../versioned_docs/version-0.74.0/auth_api.md | 89 - .../version-0.74.0/entity_media_player.md | 45 - .../version-0.74.0/entity_vacuum.md | 57 - .../version-0.74.0/hassio_addon_tutorial.md | 180 - .../internationalization_index.md | 13 - .../version-0.74.0/lovelace_custom_card.md | 211 - .../versioned_docs/version-0.76.0/auth_api.md | 128 - .../version-0.76.0/auth_auth_provider.md | 26 - .../version-0.76.0/development_environment.md | 104 - .../documentation_create_page.md | 121 - .../version-0.76.0/documentation_standards.md | 114 - .../frontend_creating_custom_panels.md | 44 - .../version-0.76.0/frontend_data.md | 139 - .../version-0.76.0/hassio_addon_config.md | 204 - .../version-0.76.0/hassio_debugging.md | 49 - .../versioned_docs/version-0.77.0/auth_api.md | 158 - .../version-0.77.0/auth_auth_module.md | 65 - .../version-0.77.0/auth_auth_provider.md | 44 - .../version-0.77.0/auth_index.md | 40 - .../config_entries_config_flow_handler.md | 80 - .../version-0.77.0/data_entry_flow_index.md | 223 - .../external_api_rest_python.md | 10 - .../version-0.77.0/frontend_data.md | 139 - .../asyncio_working_with_async.md | 108 - .../versioned_docs/version-0.78.0/auth_api.md | 223 - .../version-0.78.0/auth_auth_module.md | 65 - .../version-0.78.0/auth_index.md | 47 - .../creating_component_code_review.md | 44 - .../version-0.78.0/development_guidelines.md | 94 - .../version-0.78.0/device_registry_index.md | 74 - .../version-0.78.0/documentation_standards.md | 126 - .../version-0.78.0/external_api_websocket.md | 416 - .../version-0.78.0/frontend_add_more_info.md | 18 - .../version-0.78.0/frontend_external_auth.md | 68 - .../hassio_addon_communication.md | 42 - .../version-0.78.0/hassio_addon_config.md | 206 - .../version-0.78.0/hassio_addon_security.md | 33 - .../creating_component_code_review.md | 50 - .../creating_platform_code_review.md | 79 - .../version-0.79.0/development_environment.md | 114 - .../documentation_create_page.md | 133 - .../version-0.79.0/documentation_index.md | 38 - .../hassio_addon_communication.md | 42 - .../version-0.79.0/hassio_hass.md | 54 - .../integration_quality_scale_index.md | 51 - .../version-0.80.0/auth_index.md | 52 - .../version-0.80.0/auth_permissions.md | 93 - .../version-0.80.0/development_catching_up.md | 38 - .../version-0.80.0/development_environment.md | 111 - .../version-0.80.0/development_submitting.md | 44 - .../version-0.80.0/development_testing.md | 78 - .../documentation_create_page.md | 133 - .../version-0.80.0/documentation_index.md | 53 - .../version-0.80.0/documentation_standards.md | 126 - .../version-0.80.0/entity_sensor.md | 30 - .../version-0.80.0/entity_water_heater.md | 47 - .../version-0.80.0/frontend_architecture.md | 64 - .../hassio_addon_communication.md | 44 - .../version-0.80.0/hassio_addon_config.md | 209 - .../version-0.80.0/hassio_addon_security.md | 34 - .../version-0.80.0/hassio_debugging.md | 50 - .../integration_quality_scale_index.md | 56 - .../version-0.81.0/asyncio_index.md | 21 - .../versioned_docs/version-0.81.0/auth_api.md | 255 - .../version-0.81.0/auth_auth_module.md | 65 - .../version-0.81.0/development_index.md | 29 - .../version-0.81.0/development_testing.md | 80 - .../version-0.81.0/documentation_index.md | 53 - .../version-0.81.0/external_api_rest.md | 517 - .../external_api_server_sent_events.md | 74 - .../version-0.81.0/hassio_addon_config.md | 209 - .../version-0.82.0/architecture_hassio.md | 32 - .../asyncio_working_with_async.md | 108 - .../version-0.82.0/auth_permissions.md | 93 - .../version-0.82.0/config_entries_index.md | 39 - .../creating_component_code_review.md | 53 - .../creating_component_deps_and_reqs.md | 68 - .../creating_component_generic_discovery.md | 72 - .../version-0.82.0/development_checklist.md | 15 - .../version-0.82.0/development_guidelines.md | 100 - .../version-0.82.0/development_validation.md | 82 - .../version-0.82.0/documentation_index.md | 53 - .../version-0.82.0/entity_registry_index.md | 24 - .../version-0.82.0/entity_sensor.md | 31 - .../version-0.82.0/hassio_addon_config.md | 210 - .../version-0.82.0/hassio_addon_index.md | 19 - .../version-0.83.0/app_integration_index.md | 12 - .../app_integration_sending_data.md | 59 - .../version-0.83.0/app_integration_setup.md | 40 - .../version-0.83.0/app_integration_webview.md | 11 - .../versioned_docs/version-0.83.0/auth_api.md | 257 - .../external_api_server_sent_events.md | 74 - .../hassio_addon_presentation.md | 48 - .../version-0.83.0/hassio_addon_publishing.md | 60 - .../creating_component_code_review.md | 56 - .../version-0.84.0/external_api_rest.md | 517 - .../asyncio_categorizing_functions.md | 69 - .../version-0.85/documentation_index.md | 53 - .../version-0.85/entity_air_pollutants.md | 28 - .../version-0.85/entity_sensor.md | 31 - .../version-0.85/external_api_rest.md | 517 - .../version-0.85/frontend_add_card.md | 23 - .../version-0.85/frontend_add_more_info.md | 18 - .../version-0.86.0/development_environment.md | 111 - .../version-0.86.0/documentation_index.md | 53 - .../version-0.86.0/entity_air_quality.md | 28 - .../version-0.86.0/external_api_rest.md | 519 - .../version-0.86.0/hassio_addon_config.md | 211 - .../version-0.86.0/lovelace_custom_card.md | 211 - .../version-0.87.0/area_registry_index.md | 13 - .../version-0.87.0/development_environment.md | 112 - .../version-0.87.0/device_registry_index.md | 75 - .../documentation_create_page.md | 150 - .../version-0.87.0/documentation_standards.md | 126 - .../version-0.87.0/frontend_architecture.md | 64 - .../version-0.87.0/frontend_development.md | 107 - .../version-0.88.0/development_guidelines.md | 95 - .../version-0.88.0/entity_index.md | 104 - .../version-0.88.0/frontend_development.md | 107 - .../version-0.88.0/lovelace_custom_card.md | 227 - .../version-0.89.0/app_integration_index.md | 13 - .../app_integration_sending_data.md | 146 - .../version-0.89.0/app_integration_setup.md | 87 - .../version-0.89.0/auth_auth_module.md | 65 - .../version-0.89.0/config_entries_index.md | 127 - .../config_entries_options_flow_handler.md | 42 - .../creating_component_code_review.md | 56 - .../creating_platform_code_review.md | 79 - .../version-0.89.0/development_checklist.md | 15 - .../version-0.89.0/development_environment.md | 112 - .../version-0.89.0/device_registry_index.md | 85 - .../entity_alarm_control_panel.md | 129 - .../version-0.89.0/entity_cover.md | 189 - .../internationalization_translation.md | 43 - .../app_integration_sending_data.md | 146 - .../version-0.90.0/auth_permissions.md | 273 - .../version-0.90.0/config_entries_index.md | 136 - .../version-0.90.0/development_environment.md | 120 - .../version-0.90.0/device_registry_index.md | 85 - .../version-0.90.0/external_api_rest.md | 530 - .../version-0.90.0/external_api_websocket.md | 436 - .../version-0.90.0/hassio_addon_config.md | 211 - .../version-0.90.0/hassio_addon_tutorial.md | 182 - .../version-0.90.0/maintenance.md | 47 - .../asyncio_working_with_async.md | 108 - .../creating_component_code_review.md | 64 - .../creating_platform_example_light.md | 119 - .../creating_platform_example_sensor.md | 61 - .../version-0.91.0/dev_101_events.md | 63 - .../version-0.91.0/entity_media_player.md | 68 - .../version-0.91.0/entity_sensor.md | 32 - .../integration_quality_scale_index.md | 57 - .../app_integration_notifications.md | 239 - .../app_integration_sending_data.md | 230 - .../version-0.91.2/app_integration_sensors.md | 80 - .../version-0.91.2/app_integration_setup.md | 85 - .../version-0.91.2/auth_auth_module.md | 63 - .../config_entries_config_flow_handler.md | 93 - .../version-0.91.2/config_entries_index.md | 139 - .../config_entries_options_flow_handler.md | 47 - .../creating_component_code_review.md | 70 - .../creating_component_deps_and_reqs.md | 9 - .../creating_component_generic_discovery.md | 23 - .../creating_component_index.md | 40 - .../creating_integration_file_structure.md | 33 - .../creating_integration_manifest.md | 79 - .../creating_platform_code_review.md | 93 - .../creating_platform_example_light.md | 9 - .../creating_platform_example_sensor.md | 9 - .../version-0.91.2/creating_platform_index.md | 23 - .../version-0.91.2/dev_101_services.md | 78 - .../version-0.91.2/dev_101_states.md | 130 - .../version-0.91.2/development_checklist.md | 17 - .../version-0.91.2/development_guidelines.md | 84 - .../version-0.91.2/development_index.md | 13 - .../version-0.91.2/development_validation.md | 82 - .../version-0.91.2/entity_sensor.md | 33 - .../internationalization_translation.md | 42 - .../version-0.91.2/maintenance.md | 47 - .../version-0.92.0/app_integration_setup.md | 85 - .../version-0.92.0/auth_auth_module.md | 67 - .../creating_integration_manifest.md | 79 - .../version-0.92.0/creating_platform_index.md | 23 - .../version-0.92.0/development_submitting.md | 44 - .../version-0.92.0/entity_climate.md | 233 - .../version-0.92.0/entity_fan.md | 98 - .../version-0.92.0/entity_media_player.md | 69 - .../version-0.92.0/entity_registry_index.md | 24 - .../version-0.92.0/external_api_websocket.md | 436 - .../hassio_addon_communication.md | 46 - .../version-0.92.0/hassio_addon_config.md | 228 - .../version-0.92.0/hassio_addon_index.md | 31 - .../hassio_addon_presentation.md | 64 - .../version-0.92.0/hassio_addon_publishing.md | 60 - .../version-0.92.0/hassio_addon_security.md | 43 - .../version-0.92.0/hassio_addon_testing.md | 34 - .../version-0.92.0/hassio_debugging.md | 64 - .../version-0.92.0/hassio_hass.md | 59 - .../creating_integration_manifest.md | 79 - .../version-0.92.1/development_checklist.md | 16 - .../version-0.92.1/entity_fan.md | 98 - .../version-0.92.1/entity_light.md | 63 - .../version-0.92.1/entity_media_player.md | 76 - ...alization_custom_component_localization.md | 14 - .../version-0.93.0/auth_permissions.md | 273 - .../creating_integration_manifest.md | 79 - .../version-0.93.0/development_testing.md | 80 - .../documentation_create_page.md | 133 - .../version-0.93.0/entity_index.md | 104 - .../version-0.93.0/entity_media_player.md | 77 - .../version-0.93.0/entity_registry_index.md | 24 - .../version-0.93.0/entity_switch.md | 72 - .../version-0.93.0/hassio_addon_index.md | 31 - .../version-0.93.0/hassio_addon_security.md | 43 - .../version-0.93.0/hassio_debugging.md | 90 - .../config_entries_config_flow_handler.md | 142 - .../creating_component_code_review.md | 69 - .../creating_component_index.md | 40 - .../creating_integration_manifest.md | 139 - .../creating_platform_code_review.md | 88 - .../version-0.94.0/data_entry_flow_index.md | 284 - .../version-0.94.0/device_registry_index.md | 87 - .../version-0.94.0/entity_cover.md | 189 - .../version-0.94.0/external_api_rest.md | 552 - .../frontend_creating_custom_panels.md | 35 - .../frontend_creating_custom_ui.md | 122 - .../version-0.94.0/frontend_external_bus.md | 159 - .../hassio_addon_communication.md | 46 - .../version-0.94.0/hassio_debugging.md | 90 - .../config_entries_config_flow_handler.md | 143 - .../version-0.95.0/development_environment.md | 120 - .../version-0.95.0/development_testing.md | 80 - .../version-0.95.0/device_registry_index.md | 87 - .../version-0.95.0/documentation_standards.md | 125 - .../version-0.95.0/frontend_development.md | 105 - .../version-0.95.0/hassio_addon_tutorial.md | 182 - .../version-0.95.0/hassio_debugging.md | 91 - .../asyncio_categorizing_functions.md | 69 - .../version-0.96.0/development_environment.md | 147 - .../documentation_create_page.md | 135 - .../version-0.96.0/documentation_index.md | 53 - .../version-0.96.0/documentation_standards.md | 123 - .../version-0.96.0/entity_climate.md | 221 - .../version-0.96.0/hassio_addon_config.md | 228 - .../creating_integration_manifest.md | 137 - .../version-0.97.0/external_api_websocket.md | 437 - .../config_entries_config_flow_handler.md | 138 - .../config_entries_options_flow_handler.md | 60 - .../creating_component_generic_discovery.md | 23 - .../version-0.98.0/development_environment.md | 147 - .../version-0.98.0/development_guidelines.md | 71 - .../version-0.98.0/entity_index.md | 113 - .../entity_registry_disabled_by.md | 45 - .../version-0.98.0/hassio_addon_config.md | 229 - .../version-0.98.0/hassio_addon_tutorial.md | 182 - .../creating_component_index.md | 45 - .../version-0.99.0/dev_101_states.md | 130 - .../version-0.99.0/development_checklist.md | 17 - .../version-0.99.0/entity_weather.md | 59 - .../version-0.99.0/hassio_addon_config.md | 231 - .../version-0.99.0/lovelace_custom_card.md | 243 - .../device_automation_action.md | 29 - .../device_automation_condition.md | 29 - .../version-0.99.3/device_automation_index.md | 12 - .../device_automation_trigger.md | 29 - .../version-0.99.3/reproduce_state_index.md | 28 - .../version-0.101.0-sidebars.json | 182 - .../version-0.105.0-sidebars.json | 183 - .../version-0.72-sidebars.json | 150 - .../version-0.73.0-sidebars.json | 154 - .../version-0.74.0-sidebars.json | 151 - .../version-0.76.0-sidebars.json | 152 - .../version-0.77.0-sidebars.json | 153 - .../version-0.78.0-sidebars.json | 158 - .../version-0.79.0-sidebars.json | 161 - .../version-0.80.0-sidebars.json | 163 - .../version-0.83.0-sidebars.json | 169 - .../version-0.87.0-sidebars.json | 173 - .../version-0.89.0-sidebars.json | 174 - .../version-0.91.2-sidebars.json | 169 - .../version-0.94.0-sidebars.json | 169 - .../version-0.98.0-sidebars.json | 170 - .../version-0.99.3-sidebars.json | 177 - website/versions.json | 39 - yarn.lock | 9405 +++++++++++++++++ 912 files changed, 10434 insertions(+), 79622 deletions(-) rename {website/blog => blog}/2018-05-22-custom-ui-panels-api.md (100%) rename {website/blog => blog}/2018-06-01-071-custom-panels.md (97%) rename {website/blog => blog}/2018-07-02-trying-new-auth.md (100%) rename {website/blog => blog}/2018-08-13-deprecating-remote-package.md (100%) rename {website/blog => blog}/2019-02-19-the-great-migration.md (100%) rename {website/blog => blog}/2019-03-11-user-permissions.md (100%) rename {website/blog => blog}/2019-04-12-new-integration-structure.md (100%) rename {website/blog => blog}/2019-05-22-internet-of-things-and-the-modern-web.md (96%) rename {website/blog => blog}/2019-07-03-climate-cleanup.md (87%) rename {website/blog => blog}/2019-07-19-building-all-the-things.md (94%) rename {website/blog => blog}/2019-07-31-black.md (100%) rename {website/blog => blog}/2019-09-27-hacktoberfest.md (91%) rename {website/blog => blog}/2019-10-05-simple-mode.md (90%) rename {website/blog => blog}/2020-02-04-new-zwave.md (78%) delete mode 100644 crowdin.yaml create mode 100644 docusaurus.config.js create mode 100644 netlify.toml create mode 100644 package.json mode change 100755 => 100644 script/bootstrap mode change 100755 => 100644 script/netlify mode change 100755 => 100644 script/server mode change 100755 => 100644 script/setup rename website/sidebars.json => sidebars.js (95%) create mode 100644 src/css/custom.css create mode 100644 src/pages/index.js create mode 100644 src/pages/styles.module.css rename {website/static => static}/img/default-social.png (100%) rename {website/static => static}/img/dev-tools/about-icon.png (100%) rename {website/static => static}/img/dev-tools/events-icon.png (100%) rename {website/static => static}/img/dev-tools/mqtt-icon.png (100%) rename {website/static => static}/img/dev-tools/services-icon.png (100%) rename {website/static => static}/img/dev-tools/states-icon.png (100%) rename {website/static => static}/img/dev-tools/templates-icon.png (100%) rename {website/static => static}/img/docusaurus.svg (100%) rename {website/static => static}/img/en/architecture/component_interaction.png (100%) rename {website/static => static}/img/en/architecture/entities_architecture.png (100%) rename {website/static => static}/img/en/architecture/ha_architecture.svg (100%) rename {website/static => static}/img/en/architecture/ha_full_architecture.png (100%) create mode 100644 static/img/en/architecture/hassio.png rename {website/static => static}/img/en/architecture/home_automation_landscape.svg (100%) rename {website/static => static}/img/en/auth/architecture.png (100%) rename {website/static => static}/img/en/auth/authorize_flow.png (100%) rename {website/static => static}/img/en/auth/mfa_workflow.png (100%) rename {website/static => static}/img/en/blog/2018-07-experimental-auth/cli.png (100%) rename {website/static => static}/img/en/blog/2019-03-user-permissions/screenshot.png (100%) rename {website/static => static}/img/en/blog/2019-07-building-all-the-things/build-cabinet.jpg (100%) rename {website/static => static}/img/en/blog/2019-07-building-all-the-things/local-hosted-agent.png (100%) rename {website/static => static}/img/en/blog/2019-07-building-all-the-things/social.png (100%) rename {website/static => static}/img/en/blog/2019-07-building-all-the-things/test-results.png (100%) rename {website/static => static}/img/en/blog/2019-07-building-all-the-things/test-stages.png (100%) rename {website/static => static}/img/en/blog/2019-10-simple-mode/config-concepts.png (100%) rename {website/static => static}/img/en/development/bypass-for-network.png (100%) rename {website/static => static}/img/en/development/create-component01.png (100%) rename {website/static => static}/img/en/development/disable-cache.png (100%) rename {website/static => static}/img/en/device_registry/overview.png (100%) rename {website/static => static}/img/en/frontend/frontend-badges.png (100%) rename {website/static => static}/img/en/frontend/frontend-cards1.png (100%) create mode 100644 static/img/en/frontend/frontend-hero.png rename {website/static => static}/img/en/frontend/frontend-more-info-light.png (100%) rename {website/static => static}/img/en/frontend/hello-world-state-card.png (100%) rename {website/static => static}/img/en/frontend/lovelace-ui-comparison.png (100%) rename {website/static => static}/img/en/frontend/lovelace-ui-custom-card-screenshot.png (100%) rename {website/static => static}/img/en/hass.io/screenshots/adding_repositories.png (100%) rename {website/static => static}/img/en/hass.io/screenshots/addon-hass-configurator.png (100%) rename {website/static => static}/img/en/hass.io/screenshots/dashboard.png (100%) rename {website/static => static}/img/en/hass.io/screenshots/first-start.png (100%) rename {website/static => static}/img/en/hass.io/screenshots/local_repository.png (100%) rename {website/static => static}/img/en/hass.io/screenshots/main_panel_addon_store.png (100%) rename {website/static => static}/img/en/hass.io/screenshots/ssh-upgrade.png (100%) rename {website/static => static}/img/en/hass.io/tutorial/addon_hello_world_logs.png (100%) rename {website/static => static}/img/en/hass.io/tutorial/python3-http-server.png (100%) rename {website/static => static}/img/en/hass.io/tutorial/samba.png (100%) rename {website/static => static}/img/en/hass.io/tutorial/ssh.png (100%) rename {website/static => static}/img/en/intents/overview.png (100%) create mode 100644 static/img/favicon.ico rename {website/static => static}/img/favicon.png (100%) rename {website/static => static}/img/favicon/favicon.ico (100%) create mode 100644 static/img/logo-pretty.svg rename {website/static => static}/img/logo-responsive.svg (100%) rename {website/static => static}/img/logo-white.svg (100%) create mode 100644 static/img/logo.svg rename {website/static => static}/img/profile/paulus.jpg (100%) create mode 100644 static/img/undraw_docusaurus_mountain.svg create mode 100644 static/img/undraw_docusaurus_react.svg create mode 100644 static/img/undraw_docusaurus_tree.svg create mode 100644 static/js/discourse_discussion.jsx delete mode 100644 website/core/Footer.js delete mode 100644 website/i18n/en.json delete mode 100644 website/i18n/no-NO.json delete mode 100644 website/languages.js delete mode 100644 website/package.json delete mode 100644 website/pages/en/help-with-translations.js delete mode 100755 website/pages/en/help.js delete mode 100755 website/pages/en/index.js delete mode 100644 website/pages/en/users.js delete mode 100644 website/pages/en/versions.js delete mode 100644 website/siteConfig.js delete mode 100644 website/static/css/custom.css delete mode 100644 website/static/img/en/architecture/hassio.png delete mode 100644 website/static/img/en/frontend/frontend-hero.png delete mode 100644 website/translated_docs/ko-KR/version-0.74.0/lovelace_custom_card.md delete mode 100644 website/translated_docs/ko-KR/version-0.78.0/frontend_add_more_info.md delete mode 100644 website/translated_docs/ko-KR/version-0.78.0/frontend_external_auth.md delete mode 100644 website/translated_docs/ko-KR/version-0.78.0/hassio_addon_communication.md delete mode 100644 website/translated_docs/ko-KR/version-0.78.0/hassio_addon_config.md delete mode 100644 website/translated_docs/ko-KR/version-0.78.0/hassio_addon_security.md delete mode 100644 website/translated_docs/ko-KR/version-0.79.0/creating_component_code_review.md delete mode 100644 website/translated_docs/ko-KR/version-0.79.0/creating_platform_code_review.md delete mode 100644 website/translated_docs/ko-KR/version-0.79.0/development_environment.md delete mode 100644 website/translated_docs/ko-KR/version-0.79.0/documentation_create_page.md delete mode 100644 website/translated_docs/ko-KR/version-0.79.0/documentation_index.md delete mode 100644 website/translated_docs/ko-KR/version-0.79.0/hassio_addon_communication.md delete mode 100644 website/translated_docs/ko-KR/version-0.79.0/hassio_hass.md delete mode 100644 website/translated_docs/ko-KR/version-0.86.0/hassio_addon_config.md delete mode 100644 website/translated_docs/ko-KR/version-0.87.0/area_registry_index.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_component_code_review.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_component_deps_and_reqs.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_component_generic_discovery.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_component_index.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_integration_file_structure.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_integration_manifest.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_platform_code_review.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_platform_example_light.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_platform_example_sensor.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_platform_index.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/dev_101_services.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/dev_101_states.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/development_checklist.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/development_guidelines.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/development_index.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/development_validation.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/entity_sensor.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/internationalization_translation.md delete mode 100644 website/translated_docs/ko-KR/version-0.91.2/maintenance.md delete mode 100644 website/translated_docs/ko-KR/version-0.92.0/app_integration_setup.md delete mode 100644 website/translated_docs/ko-KR/version-0.92.0/auth_auth_module.md delete mode 100644 website/translated_docs/ko-KR/version-0.92.0/creating_integration_manifest.md delete mode 100644 website/translated_docs/ko-KR/version-0.92.0/creating_platform_index.md delete mode 100644 website/translated_docs/ko-KR/version-0.92.0/development_submitting.md delete mode 100644 website/translated_docs/ko-KR/version-0.92.0/entity_climate.md delete mode 100644 website/translated_docs/ko-KR/version-0.92.0/entity_fan.md delete mode 100644 website/translated_docs/ko-KR/version-0.92.0/entity_registry_index.md delete mode 100644 website/translated_docs/ko/app_integration_notifications.md delete mode 100644 website/translated_docs/nl/app_integration_index.md delete mode 100644 website/translated_docs/nl/app_integration_notifications.md delete mode 100644 website/translated_docs/nl/app_integration_sending_data.md delete mode 100644 website/translated_docs/nl/app_integration_sensors.md delete mode 100644 website/translated_docs/nl/app_integration_setup.md delete mode 100644 website/translated_docs/nl/app_integration_webview.md delete mode 100644 website/translated_docs/nl/architecture_components.md delete mode 100644 website/translated_docs/nl/architecture_entities.md delete mode 100644 website/translated_docs/nl/architecture_hassio.md delete mode 100644 website/translated_docs/nl/architecture_index.md delete mode 100644 website/translated_docs/nl/area_registry_index.md delete mode 100644 website/translated_docs/nl/asyncio_101.md delete mode 100644 website/translated_docs/nl/asyncio_categorizing_functions.md delete mode 100644 website/translated_docs/nl/asyncio_index.md delete mode 100644 website/translated_docs/nl/asyncio_working_with_async.md delete mode 100644 website/translated_docs/nl/auth_api.md delete mode 100644 website/translated_docs/nl/auth_auth_module.md delete mode 100644 website/translated_docs/nl/auth_auth_provider.md delete mode 100644 website/translated_docs/nl/auth_index.md delete mode 100644 website/translated_docs/nl/auth_permissions.md delete mode 100644 website/translated_docs/nl/config_entries_config_flow_handler.md delete mode 100644 website/translated_docs/nl/config_entries_index.md delete mode 100644 website/translated_docs/nl/config_entries_options_flow_handler.md delete mode 100644 website/translated_docs/nl/configuration_yaml_index.md delete mode 100644 website/translated_docs/nl/creating_component_code_review.md delete mode 100644 website/translated_docs/nl/creating_component_deps_and_reqs.md delete mode 100644 website/translated_docs/nl/creating_component_generic_discovery.md delete mode 100644 website/translated_docs/nl/creating_component_index.md delete mode 100644 website/translated_docs/nl/creating_integration_file_structure.md delete mode 100644 website/translated_docs/nl/creating_integration_manifest.md delete mode 100644 website/translated_docs/nl/creating_platform_code_review.md delete mode 100644 website/translated_docs/nl/creating_platform_example_light.md delete mode 100644 website/translated_docs/nl/creating_platform_example_sensor.md delete mode 100644 website/translated_docs/nl/creating_platform_index.md delete mode 100644 website/translated_docs/nl/data_entry_flow_index.md delete mode 100644 website/translated_docs/nl/dev_101_config.md delete mode 100644 website/translated_docs/nl/dev_101_events.md delete mode 100644 website/translated_docs/nl/dev_101_hass.md delete mode 100644 website/translated_docs/nl/dev_101_index.md delete mode 100644 website/translated_docs/nl/dev_101_services.md delete mode 100644 website/translated_docs/nl/dev_101_states.md delete mode 100644 website/translated_docs/nl/development_catching_up.md delete mode 100644 website/translated_docs/nl/development_checklist.md delete mode 100644 website/translated_docs/nl/development_environment.md delete mode 100644 website/translated_docs/nl/development_guidelines.md delete mode 100644 website/translated_docs/nl/development_index.md delete mode 100644 website/translated_docs/nl/development_submitting.md delete mode 100644 website/translated_docs/nl/development_testing.md delete mode 100644 website/translated_docs/nl/development_typing.md delete mode 100644 website/translated_docs/nl/development_validation.md delete mode 100644 website/translated_docs/nl/device_registry_index.md delete mode 100644 website/translated_docs/nl/documentation_create_page.md delete mode 100644 website/translated_docs/nl/documentation_index.md delete mode 100644 website/translated_docs/nl/documentation_standards.md delete mode 100644 website/translated_docs/nl/entity_air_quality.md delete mode 100644 website/translated_docs/nl/entity_alarm_control_panel.md delete mode 100644 website/translated_docs/nl/entity_binary_sensor.md delete mode 100644 website/translated_docs/nl/entity_climate.md delete mode 100644 website/translated_docs/nl/entity_cover.md delete mode 100644 website/translated_docs/nl/entity_fan.md delete mode 100644 website/translated_docs/nl/entity_index.md delete mode 100644 website/translated_docs/nl/entity_light.md delete mode 100644 website/translated_docs/nl/entity_lock.md delete mode 100644 website/translated_docs/nl/entity_media_player.md delete mode 100644 website/translated_docs/nl/entity_registry_index.md delete mode 100644 website/translated_docs/nl/entity_remote.md delete mode 100644 website/translated_docs/nl/entity_sensor.md delete mode 100644 website/translated_docs/nl/entity_switch.md delete mode 100644 website/translated_docs/nl/entity_vacuum.md delete mode 100644 website/translated_docs/nl/entity_water_heater.md delete mode 100644 website/translated_docs/nl/entity_weather.md delete mode 100644 website/translated_docs/nl/external_api_rest.md delete mode 100644 website/translated_docs/nl/external_api_rest_python.md delete mode 100644 website/translated_docs/nl/external_api_server_sent_events.md delete mode 100644 website/translated_docs/nl/external_api_websocket.md delete mode 100644 website/translated_docs/nl/frontend_add_card.md delete mode 100644 website/translated_docs/nl/frontend_add_more_info.md delete mode 100644 website/translated_docs/no-NO/app_integration_notifications.md delete mode 100644 website/translated_docs/no-NO/app_integration_sensors.md delete mode 100644 website/translated_docs/no-NO/app_integration_setup.md delete mode 100644 website/translated_docs/no-NO/app_integration_webview.md delete mode 100644 website/translated_docs/no-NO/architecture_components.md delete mode 100644 website/translated_docs/no-NO/architecture_entities.md delete mode 100644 website/translated_docs/no-NO/architecture_hassio.md delete mode 100644 website/translated_docs/no-NO/architecture_index.md delete mode 100644 website/translated_docs/no-NO/area_registry_index.md delete mode 100644 website/translated_docs/no-NO/asyncio_101.md delete mode 100644 website/translated_docs/no-NO/asyncio_categorizing_functions.md delete mode 100644 website/translated_docs/no-NO/asyncio_index.md delete mode 100644 website/translated_docs/no-NO/asyncio_working_with_async.md delete mode 100644 website/translated_docs/no-NO/auth_api.md delete mode 100644 website/translated_docs/no-NO/auth_auth_module.md delete mode 100644 website/translated_docs/no-NO/auth_auth_provider.md delete mode 100644 website/translated_docs/no-NO/auth_index.md delete mode 100644 website/translated_docs/no-NO/auth_permissions.md delete mode 100644 website/translated_docs/no-NO/config_entries_config_flow_handler.md delete mode 100644 website/translated_docs/no-NO/config_entries_index.md delete mode 100644 website/translated_docs/no-NO/creating_component_index.md delete mode 100644 website/translated_docs/no-NO/creating_integration_file_structure.md delete mode 100644 website/translated_docs/no-NO/creating_integration_manifest.md delete mode 100644 website/translated_docs/no-NO/creating_platform_code_review.md delete mode 100644 website/translated_docs/no-NO/creating_platform_example_light.md delete mode 100644 website/translated_docs/no-NO/creating_platform_example_sensor.md delete mode 100644 website/translated_docs/no-NO/creating_platform_index.md delete mode 100644 website/translated_docs/no-NO/data_entry_flow_index.md delete mode 100644 website/translated_docs/no-NO/dev_101_config.md delete mode 100644 website/translated_docs/no-NO/dev_101_events.md delete mode 100644 website/translated_docs/no-NO/dev_101_hass.md delete mode 100644 website/translated_docs/no-NO/dev_101_index.md delete mode 100644 website/translated_docs/no-NO/dev_101_services.md delete mode 100644 website/translated_docs/no-NO/dev_101_states.md delete mode 100644 website/translated_docs/no-NO/development_catching_up.md delete mode 100644 website/translated_docs/no-NO/development_checklist.md delete mode 100644 website/translated_docs/no-NO/development_environment.md delete mode 100644 website/translated_docs/no-NO/development_guidelines.md delete mode 100644 website/translated_docs/no-NO/development_index.md delete mode 100644 website/translated_docs/no-NO/development_submitting.md delete mode 100644 website/translated_docs/no-NO/development_testing.md delete mode 100644 website/translated_docs/no-NO/development_typing.md delete mode 100644 website/translated_docs/no-NO/development_validation.md delete mode 100644 website/translated_docs/no-NO/device_registry_index.md delete mode 100644 website/translated_docs/no-NO/documentation_create_page.md delete mode 100644 website/translated_docs/no-NO/documentation_index.md delete mode 100644 website/translated_docs/no-NO/documentation_standards.md delete mode 100644 website/translated_docs/no-NO/entity_air_quality.md delete mode 100644 website/translated_docs/no-NO/entity_alarm_control_panel.md delete mode 100644 website/translated_docs/no-NO/entity_binary_sensor.md delete mode 100644 website/translated_docs/no-NO/entity_climate.md delete mode 100644 website/translated_docs/no-NO/entity_cover.md delete mode 100644 website/translated_docs/no-NO/entity_fan.md delete mode 100644 website/translated_docs/no-NO/entity_index.md delete mode 100644 website/translated_docs/no-NO/entity_light.md delete mode 100644 website/translated_docs/no-NO/entity_lock.md delete mode 100644 website/translated_docs/no-NO/entity_media_player.md delete mode 100644 website/translated_docs/no-NO/entity_registry_index.md delete mode 100644 website/translated_docs/no-NO/entity_remote.md delete mode 100644 website/translated_docs/no-NO/entity_sensor.md delete mode 100644 website/translated_docs/no-NO/entity_switch.md delete mode 100644 website/translated_docs/no-NO/entity_vacuum.md delete mode 100644 website/translated_docs/no-NO/entity_water_heater.md delete mode 100644 website/translated_docs/no-NO/entity_weather.md delete mode 100644 website/translated_docs/no-NO/external_api_rest.md delete mode 100644 website/translated_docs/no-NO/external_api_rest_python.md delete mode 100644 website/translated_docs/no-NO/external_api_server_sent_events.md delete mode 100644 website/translated_docs/no-NO/external_api_websocket.md delete mode 100644 website/translated_docs/no-NO/frontend_add_card.md delete mode 100644 website/translated_docs/no-NO/frontend_add_more_info.md delete mode 100644 website/translated_docs/no-NO/frontend_add_websocket_api.md delete mode 100644 website/translated_docs/no-NO/frontend_architecture.md delete mode 100644 website/translated_docs/no-NO/frontend_creating_custom_panels.md delete mode 100644 website/translated_docs/no-NO/frontend_creating_custom_ui.md delete mode 100644 website/translated_docs/no-NO/frontend_data.md delete mode 100644 website/translated_docs/no-NO/frontend_development.md delete mode 100644 website/translated_docs/no-NO/frontend_external_auth.md delete mode 100644 website/translated_docs/no-NO/frontend_index.md delete mode 100644 website/translated_docs/no-NO/hassio_addon_communication.md delete mode 100644 website/translated_docs/no-NO/hassio_addon_config.md delete mode 100644 website/translated_docs/no-NO/hassio_addon_index.md delete mode 100644 website/translated_docs/no-NO/hassio_addon_presentation.md delete mode 100644 website/translated_docs/no-NO/hassio_addon_publishing.md delete mode 100644 website/translated_docs/no-NO/hassio_addon_repository.md delete mode 100644 website/translated_docs/no-NO/hassio_addon_security.md delete mode 100644 website/translated_docs/no-NO/hassio_addon_testing.md delete mode 100644 website/translated_docs/no-NO/hassio_addon_tutorial.md delete mode 100644 website/translated_docs/no-NO/hassio_debugging.md delete mode 100644 website/translated_docs/no-NO/hassio_hass.md delete mode 100644 website/translated_docs/no-NO/integration_quality_scale_index.md delete mode 100644 website/translated_docs/no-NO/intent_builtin.md delete mode 100644 website/translated_docs/no-NO/intent_conversation.md delete mode 100644 website/translated_docs/no-NO/intent_firing.md delete mode 100644 website/translated_docs/no-NO/intent_handling.md delete mode 100644 website/translated_docs/no-NO/intent_index.md delete mode 100644 website/translated_docs/no-NO/internationalization_backend_localization.md delete mode 100644 website/translated_docs/no-NO/internationalization_custom_component_localization.md delete mode 100644 website/translated_docs/no-NO/internationalization_index.md delete mode 100644 website/translated_docs/no-NO/internationalization_translation.md delete mode 100644 website/translated_docs/no-NO/lovelace_custom_card.md delete mode 100644 website/translated_docs/no-NO/lovelace_index.md delete mode 100644 website/translated_docs/no-NO/maintenance.md delete mode 100644 website/translated_docs/no-NO/misc.md delete mode 100644 website/translated_docs/no-NO/releasing.md delete mode 100644 website/translated_docs/pl/app_integration_index.md delete mode 100644 website/translated_docs/pl/app_integration_notifications.md delete mode 100644 website/translated_docs/pl/app_integration_sending_data.md delete mode 100644 website/translated_docs/pl/app_integration_sensors.md delete mode 100644 website/translated_docs/pl/app_integration_setup.md delete mode 100644 website/translated_docs/pl/app_integration_webview.md delete mode 100644 website/translated_docs/pl/architecture_components.md delete mode 100644 website/translated_docs/pl/architecture_entities.md delete mode 100644 website/translated_docs/pl/architecture_hassio.md delete mode 100644 website/translated_docs/pl/architecture_index.md delete mode 100644 website/translated_docs/pl/area_registry_index.md delete mode 100644 website/translated_docs/pl/asyncio_101.md delete mode 100644 website/translated_docs/pl/asyncio_categorizing_functions.md delete mode 100644 website/translated_docs/pl/asyncio_index.md delete mode 100644 website/translated_docs/pl/asyncio_working_with_async.md delete mode 100644 website/translated_docs/pl/auth_api.md delete mode 100644 website/translated_docs/pl/auth_auth_module.md delete mode 100644 website/translated_docs/pl/auth_auth_provider.md delete mode 100644 website/translated_docs/pl/auth_index.md delete mode 100644 website/translated_docs/pl/auth_permissions.md delete mode 100644 website/translated_docs/pl/config_entries_config_flow_handler.md delete mode 100644 website/translated_docs/pl/config_entries_index.md delete mode 100644 website/translated_docs/pl/config_entries_options_flow_handler.md delete mode 100644 website/translated_docs/pl/configuration_yaml_index.md delete mode 100644 website/translated_docs/pl/creating_component_code_review.md delete mode 100644 website/translated_docs/pl/creating_component_deps_and_reqs.md delete mode 100644 website/translated_docs/pl/creating_component_generic_discovery.md delete mode 100644 website/translated_docs/pl/creating_component_index.md delete mode 100644 website/translated_docs/pl/creating_integration_file_structure.md delete mode 100644 website/translated_docs/pl/creating_integration_manifest.md delete mode 100644 website/translated_docs/pl/creating_platform_code_review.md delete mode 100644 website/translated_docs/pl/creating_platform_example_light.md delete mode 100644 website/translated_docs/pl/creating_platform_example_sensor.md delete mode 100644 website/translated_docs/pl/creating_platform_index.md delete mode 100644 website/translated_docs/pl/data_entry_flow_index.md delete mode 100644 website/translated_docs/pl/dev_101_config.md delete mode 100644 website/translated_docs/pl/dev_101_events.md delete mode 100644 website/translated_docs/pl/dev_101_hass.md delete mode 100644 website/translated_docs/pl/dev_101_index.md delete mode 100644 website/translated_docs/pl/dev_101_services.md delete mode 100644 website/translated_docs/pl/dev_101_states.md delete mode 100644 website/translated_docs/pl/development_catching_up.md delete mode 100644 website/translated_docs/pl/development_checklist.md delete mode 100644 website/translated_docs/pl/development_environment.md delete mode 100644 website/translated_docs/pl/development_guidelines.md delete mode 100644 website/translated_docs/pl/development_index.md delete mode 100644 website/translated_docs/pl/development_submitting.md delete mode 100644 website/translated_docs/pl/development_testing.md delete mode 100644 website/translated_docs/pl/development_typing.md delete mode 100644 website/translated_docs/pl/development_validation.md delete mode 100644 website/translated_docs/pl/device_registry_index.md delete mode 100644 website/translated_docs/pl/documentation_create_page.md delete mode 100644 website/translated_docs/pl/documentation_index.md delete mode 100644 website/translated_docs/pl/documentation_standards.md delete mode 100644 website/translated_docs/pl/entity_air_quality.md delete mode 100644 website/translated_docs/pl/entity_alarm_control_panel.md delete mode 100644 website/translated_docs/pl/entity_binary_sensor.md delete mode 100644 website/translated_docs/pl/entity_climate.md delete mode 100644 website/translated_docs/pl/entity_cover.md delete mode 100644 website/translated_docs/pl/entity_fan.md delete mode 100644 website/translated_docs/pl/entity_index.md delete mode 100644 website/translated_docs/pl/entity_light.md delete mode 100644 website/translated_docs/pl/entity_lock.md delete mode 100644 website/translated_docs/pl/entity_media_player.md delete mode 100644 website/translated_docs/pl/entity_registry_index.md delete mode 100644 website/translated_docs/pl/entity_remote.md delete mode 100644 website/translated_docs/pl/entity_sensor.md delete mode 100644 website/translated_docs/pl/entity_switch.md delete mode 100644 website/translated_docs/pl/entity_vacuum.md delete mode 100644 website/translated_docs/pl/entity_water_heater.md delete mode 100644 website/translated_docs/pl/entity_weather.md delete mode 100644 website/translated_docs/pl/external_api_rest.md delete mode 100644 website/translated_docs/pl/external_api_rest_python.md delete mode 100644 website/translated_docs/pl/external_api_server_sent_events.md delete mode 100644 website/translated_docs/pl/external_api_websocket.md delete mode 100644 website/translated_docs/pl/frontend_add_card.md delete mode 100644 website/versioned_docs/version-0.100.0/creating_component_index.md delete mode 100644 website/versioned_docs/version-0.100.0/creating_platform_code_review.md delete mode 100644 website/versioned_docs/version-0.100.0/development_environment.md delete mode 100644 website/versioned_docs/version-0.100.0/external_api_rest.md delete mode 100644 website/versioned_docs/version-0.100.0/hassio_hass.md delete mode 100644 website/versioned_docs/version-0.101.0/api_lib_auth.md delete mode 100644 website/versioned_docs/version-0.101.0/api_lib_data_models.md delete mode 100644 website/versioned_docs/version-0.101.0/api_lib_index.md delete mode 100644 website/versioned_docs/version-0.101.0/config_entries_config_flow_handler.md delete mode 100644 website/versioned_docs/version-0.101.0/config_entries_options_flow_handler.md delete mode 100644 website/versioned_docs/version-0.101.0/data_entry_flow_index.md delete mode 100644 website/versioned_docs/version-0.101.0/documentation_create_page.md delete mode 100644 website/versioned_docs/version-0.101.0/documentation_index.md delete mode 100644 website/versioned_docs/version-0.101.0/documentation_standards.md delete mode 100644 website/versioned_docs/version-0.101.0/entity_climate.md delete mode 100644 website/versioned_docs/version-0.101.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.101.0/integration_quality_scale_index.md delete mode 100644 website/versioned_docs/version-0.101.0/lovelace_custom_card.md delete mode 100644 website/versioned_docs/version-0.102.0/app_integration_setup.md delete mode 100644 website/versioned_docs/version-0.102.0/config_entries_config_flow_handler.md delete mode 100644 website/versioned_docs/version-0.102.0/development_testing.md delete mode 100644 website/versioned_docs/version-0.102.0/entity_index.md delete mode 100644 website/versioned_docs/version-0.102.0/frontend_external_auth.md delete mode 100644 website/versioned_docs/version-0.102.0/hassio_addon_communication.md delete mode 100644 website/versioned_docs/version-0.102.0/lovelace_custom_card.md delete mode 100644 website/versioned_docs/version-0.103.0/api_lib_auth.md delete mode 100644 website/versioned_docs/version-0.103.0/app_integration_sending_data.md delete mode 100644 website/versioned_docs/version-0.103.0/config_entries_config_flow_handler.md delete mode 100644 website/versioned_docs/version-0.103.0/creating_integration_manifest.md delete mode 100644 website/versioned_docs/version-0.103.0/development_testing.md delete mode 100644 website/versioned_docs/version-0.103.0/external_api_rest.md delete mode 100644 website/versioned_docs/version-0.103.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.103.0/internationalization_translation.md delete mode 100644 website/versioned_docs/version-0.103.0/maintenance.md delete mode 100644 website/versioned_docs/version-0.104.0/api_lib_auth.md delete mode 100644 website/versioned_docs/version-0.104.0/api_lib_data_models.md delete mode 100644 website/versioned_docs/version-0.104.0/api_lib_index.md delete mode 100644 website/versioned_docs/version-0.104.0/app_integration_setup.md delete mode 100644 website/versioned_docs/version-0.104.0/asyncio_categorizing_functions.md delete mode 100644 website/versioned_docs/version-0.104.0/asyncio_working_with_async.md delete mode 100644 website/versioned_docs/version-0.104.0/auth_api.md delete mode 100644 website/versioned_docs/version-0.104.0/auth_auth_provider.md delete mode 100644 website/versioned_docs/version-0.104.0/auth_permissions.md delete mode 100644 website/versioned_docs/version-0.104.0/config_entries_config_flow_handler.md delete mode 100644 website/versioned_docs/version-0.104.0/config_entries_index.md delete mode 100644 website/versioned_docs/version-0.104.0/config_entries_options_flow_handler.md delete mode 100644 website/versioned_docs/version-0.104.0/configuration_yaml_index.md delete mode 100644 website/versioned_docs/version-0.104.0/creating_component_code_review.md delete mode 100644 website/versioned_docs/version-0.104.0/creating_component_index.md delete mode 100644 website/versioned_docs/version-0.104.0/creating_integration_manifest.md delete mode 100644 website/versioned_docs/version-0.104.0/creating_platform_code_review.md delete mode 100644 website/versioned_docs/version-0.104.0/data_entry_flow_index.md delete mode 100644 website/versioned_docs/version-0.104.0/dev_101_config.md delete mode 100644 website/versioned_docs/version-0.104.0/dev_101_events.md delete mode 100644 website/versioned_docs/version-0.104.0/dev_101_index.md delete mode 100644 website/versioned_docs/version-0.104.0/dev_101_services.md delete mode 100644 website/versioned_docs/version-0.104.0/dev_101_states.md delete mode 100644 website/versioned_docs/version-0.104.0/development_catching_up.md delete mode 100644 website/versioned_docs/version-0.104.0/development_environment.md delete mode 100644 website/versioned_docs/version-0.104.0/development_guidelines.md delete mode 100644 website/versioned_docs/version-0.104.0/development_testing.md delete mode 100644 website/versioned_docs/version-0.104.0/development_validation.md delete mode 100644 website/versioned_docs/version-0.104.0/device_registry_index.md delete mode 100644 website/versioned_docs/version-0.104.0/documentation_create_page.md delete mode 100644 website/versioned_docs/version-0.104.0/documentation_index.md delete mode 100644 website/versioned_docs/version-0.104.0/entity_cover.md delete mode 100644 website/versioned_docs/version-0.104.0/entity_fan.md delete mode 100644 website/versioned_docs/version-0.104.0/entity_index.md delete mode 100644 website/versioned_docs/version-0.104.0/entity_light.md delete mode 100644 website/versioned_docs/version-0.104.0/entity_media_player.md delete mode 100644 website/versioned_docs/version-0.104.0/entity_switch.md delete mode 100644 website/versioned_docs/version-0.104.0/external_api_rest.md delete mode 100644 website/versioned_docs/version-0.104.0/external_api_server_sent_events.md delete mode 100644 website/versioned_docs/version-0.104.0/frontend_add_websocket_api.md delete mode 100644 website/versioned_docs/version-0.104.0/frontend_creating_custom_ui.md delete mode 100644 website/versioned_docs/version-0.104.0/frontend_development.md delete mode 100644 website/versioned_docs/version-0.104.0/frontend_external_auth.md delete mode 100644 website/versioned_docs/version-0.104.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.104.0/hassio_addon_publishing.md delete mode 100644 website/versioned_docs/version-0.104.0/hassio_addon_tutorial.md delete mode 100644 website/versioned_docs/version-0.104.0/hassio_debugging.md delete mode 100644 website/versioned_docs/version-0.104.0/hassio_hass.md delete mode 100644 website/versioned_docs/version-0.104.0/intent_conversation.md delete mode 100644 website/versioned_docs/version-0.104.0/intent_firing.md delete mode 100644 website/versioned_docs/version-0.104.0/intent_handling.md delete mode 100644 website/versioned_docs/version-0.104.0/internationalization_backend_localization.md delete mode 100644 website/versioned_docs/version-0.104.0/internationalization_translation.md delete mode 100644 website/versioned_docs/version-0.104.0/lovelace_custom_card.md delete mode 100644 website/versioned_docs/version-0.104.0/maintenance.md delete mode 100644 website/versioned_docs/version-0.104.0/reproduce_state_index.md delete mode 100644 website/versioned_docs/version-0.105.0/app_integration_notifications.md delete mode 100644 website/versioned_docs/version-0.105.0/app_integration_sensors.md delete mode 100644 website/versioned_docs/version-0.105.0/dev_101_services.md delete mode 100644 website/versioned_docs/version-0.105.0/device_automation_condition.md delete mode 100644 website/versioned_docs/version-0.105.0/documentation_standards.md delete mode 100644 website/versioned_docs/version-0.105.0/entity_cover.md delete mode 100644 website/versioned_docs/version-0.105.0/entity_index.md delete mode 100644 website/versioned_docs/version-0.105.0/entity_lock.md delete mode 100644 website/versioned_docs/version-0.105.0/entity_registry_disabled_by.md delete mode 100644 website/versioned_docs/version-0.105.0/external_api_rest.md delete mode 100644 website/versioned_docs/version-0.105.0/frontend_data.md delete mode 100644 website/versioned_docs/version-0.105.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.105.0/hassio_addon_presentation.md delete mode 100644 website/versioned_docs/version-0.105.0/integration_fetching_data.md delete mode 100644 website/versioned_docs/version-0.105.0/integration_quality_scale_index.md delete mode 100644 website/versioned_docs/version-0.72/architecture_components.md delete mode 100644 website/versioned_docs/version-0.72/architecture_entities.md delete mode 100644 website/versioned_docs/version-0.72/architecture_hassio.md delete mode 100644 website/versioned_docs/version-0.72/architecture_index.md delete mode 100644 website/versioned_docs/version-0.72/asyncio_101.md delete mode 100644 website/versioned_docs/version-0.72/asyncio_categorizing_functions.md delete mode 100644 website/versioned_docs/version-0.72/asyncio_index.md delete mode 100644 website/versioned_docs/version-0.72/asyncio_working_with_async.md delete mode 100644 website/versioned_docs/version-0.72/auth_api.md delete mode 100644 website/versioned_docs/version-0.72/auth_auth_provider.md delete mode 100644 website/versioned_docs/version-0.72/auth_index.md delete mode 100644 website/versioned_docs/version-0.72/config_entries_config_flow_handler.md delete mode 100644 website/versioned_docs/version-0.72/config_entries_index.md delete mode 100644 website/versioned_docs/version-0.72/configuration_yaml_index.md delete mode 100644 website/versioned_docs/version-0.72/creating_component_code_review.md delete mode 100644 website/versioned_docs/version-0.72/creating_component_deps_and_reqs.md delete mode 100644 website/versioned_docs/version-0.72/creating_component_discovery.md delete mode 100644 website/versioned_docs/version-0.72/creating_component_events.md delete mode 100644 website/versioned_docs/version-0.72/creating_component_generic_discovery.md delete mode 100644 website/versioned_docs/version-0.72/creating_component_index.md delete mode 100644 website/versioned_docs/version-0.72/creating_component_loading.md delete mode 100644 website/versioned_docs/version-0.72/creating_component_states.md delete mode 100644 website/versioned_docs/version-0.72/creating_platform_code_review.md delete mode 100644 website/versioned_docs/version-0.72/creating_platform_example_light.md delete mode 100644 website/versioned_docs/version-0.72/creating_platform_example_sensor.md delete mode 100644 website/versioned_docs/version-0.72/creating_platform_index.md delete mode 100644 website/versioned_docs/version-0.72/data_entry_flow_index.md delete mode 100644 website/versioned_docs/version-0.72/dev_101_config.md delete mode 100644 website/versioned_docs/version-0.72/dev_101_events.md delete mode 100644 website/versioned_docs/version-0.72/dev_101_hass.md delete mode 100644 website/versioned_docs/version-0.72/dev_101_index.md delete mode 100644 website/versioned_docs/version-0.72/dev_101_services.md delete mode 100644 website/versioned_docs/version-0.72/dev_101_states.md delete mode 100644 website/versioned_docs/version-0.72/development_catching_up.md delete mode 100644 website/versioned_docs/version-0.72/development_checklist.md delete mode 100644 website/versioned_docs/version-0.72/development_environment.md delete mode 100644 website/versioned_docs/version-0.72/development_guidelines.md delete mode 100644 website/versioned_docs/version-0.72/development_index.md delete mode 100644 website/versioned_docs/version-0.72/development_submitting.md delete mode 100644 website/versioned_docs/version-0.72/development_testing.md delete mode 100644 website/versioned_docs/version-0.72/development_typing.md delete mode 100644 website/versioned_docs/version-0.72/development_validation.md delete mode 100644 website/versioned_docs/version-0.72/entity_alarm_control_panel.md delete mode 100644 website/versioned_docs/version-0.72/entity_binary_sensor.md delete mode 100644 website/versioned_docs/version-0.72/entity_climate.md delete mode 100644 website/versioned_docs/version-0.72/entity_cover.md delete mode 100644 website/versioned_docs/version-0.72/entity_fan.md delete mode 100644 website/versioned_docs/version-0.72/entity_index.md delete mode 100644 website/versioned_docs/version-0.72/entity_light.md delete mode 100644 website/versioned_docs/version-0.72/entity_lock.md delete mode 100644 website/versioned_docs/version-0.72/entity_media_player.md delete mode 100644 website/versioned_docs/version-0.72/entity_registry_index.md delete mode 100644 website/versioned_docs/version-0.72/entity_remote.md delete mode 100644 website/versioned_docs/version-0.72/entity_sensor.md delete mode 100644 website/versioned_docs/version-0.72/entity_switch.md delete mode 100644 website/versioned_docs/version-0.72/entity_vacuum.md delete mode 100644 website/versioned_docs/version-0.72/entity_weather.md delete mode 100644 website/versioned_docs/version-0.72/external_api_rest.md delete mode 100644 website/versioned_docs/version-0.72/external_api_rest_python.md delete mode 100644 website/versioned_docs/version-0.72/external_api_server_sent_events.md delete mode 100644 website/versioned_docs/version-0.72/external_api_websocket.md delete mode 100644 website/versioned_docs/version-0.72/frontend_add_card.md delete mode 100644 website/versioned_docs/version-0.72/frontend_add_more_info.md delete mode 100644 website/versioned_docs/version-0.72/frontend_add_websocket_api.md delete mode 100644 website/versioned_docs/version-0.72/frontend_architecture.md delete mode 100644 website/versioned_docs/version-0.72/frontend_creating_custom_panels.md delete mode 100644 website/versioned_docs/version-0.72/frontend_creating_custom_ui.md delete mode 100644 website/versioned_docs/version-0.72/frontend_development.md delete mode 100644 website/versioned_docs/version-0.72/frontend_index.md delete mode 100644 website/versioned_docs/version-0.72/hassio_addon_communication.md delete mode 100644 website/versioned_docs/version-0.72/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.72/hassio_addon_index.md delete mode 100644 website/versioned_docs/version-0.72/hassio_addon_presentation.md delete mode 100644 website/versioned_docs/version-0.72/hassio_addon_publishing.md delete mode 100644 website/versioned_docs/version-0.72/hassio_addon_repository.md delete mode 100644 website/versioned_docs/version-0.72/hassio_addon_testing.md delete mode 100644 website/versioned_docs/version-0.72/hassio_addon_tutorial.md delete mode 100644 website/versioned_docs/version-0.72/hassio_debugging.md delete mode 100644 website/versioned_docs/version-0.72/hassio_hass.md delete mode 100644 website/versioned_docs/version-0.72/intent_builtin.md delete mode 100644 website/versioned_docs/version-0.72/intent_conversation.md delete mode 100644 website/versioned_docs/version-0.72/intent_firing.md delete mode 100644 website/versioned_docs/version-0.72/intent_handling.md delete mode 100644 website/versioned_docs/version-0.72/intent_index.md delete mode 100644 website/versioned_docs/version-0.72/internationalization_backend_localization.md delete mode 100644 website/versioned_docs/version-0.72/internationalization_custom_component_localization.md delete mode 100644 website/versioned_docs/version-0.72/internationalization_index.md delete mode 100644 website/versioned_docs/version-0.72/internationalization_translation.md delete mode 100644 website/versioned_docs/version-0.72/lovelace_card_types.md delete mode 100644 website/versioned_docs/version-0.72/lovelace_custom_card.md delete mode 100644 website/versioned_docs/version-0.72/lovelace_index.md delete mode 100644 website/versioned_docs/version-0.72/maintenance.md delete mode 100644 website/versioned_docs/version-0.72/misc.md delete mode 100644 website/versioned_docs/version-0.72/releasing.md delete mode 100644 website/versioned_docs/version-0.73.0/auth_api.md delete mode 100644 website/versioned_docs/version-0.73.0/development_guidelines.md delete mode 100644 website/versioned_docs/version-0.73.0/documentation_create_page.md delete mode 100644 website/versioned_docs/version-0.73.0/documentation_index.md delete mode 100644 website/versioned_docs/version-0.73.0/documentation_standards.md delete mode 100644 website/versioned_docs/version-0.73.0/frontend_development.md delete mode 100644 website/versioned_docs/version-0.73.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.73.0/lovelace_custom_card.md delete mode 100644 website/versioned_docs/version-0.73.0/lovelace_index.md delete mode 100644 website/versioned_docs/version-0.74.0/asyncio_working_with_async.md delete mode 100644 website/versioned_docs/version-0.74.0/auth_api.md delete mode 100644 website/versioned_docs/version-0.74.0/entity_media_player.md delete mode 100644 website/versioned_docs/version-0.74.0/entity_vacuum.md delete mode 100644 website/versioned_docs/version-0.74.0/hassio_addon_tutorial.md delete mode 100644 website/versioned_docs/version-0.74.0/internationalization_index.md delete mode 100644 website/versioned_docs/version-0.74.0/lovelace_custom_card.md delete mode 100644 website/versioned_docs/version-0.76.0/auth_api.md delete mode 100644 website/versioned_docs/version-0.76.0/auth_auth_provider.md delete mode 100644 website/versioned_docs/version-0.76.0/development_environment.md delete mode 100644 website/versioned_docs/version-0.76.0/documentation_create_page.md delete mode 100644 website/versioned_docs/version-0.76.0/documentation_standards.md delete mode 100644 website/versioned_docs/version-0.76.0/frontend_creating_custom_panels.md delete mode 100644 website/versioned_docs/version-0.76.0/frontend_data.md delete mode 100644 website/versioned_docs/version-0.76.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.76.0/hassio_debugging.md delete mode 100644 website/versioned_docs/version-0.77.0/auth_api.md delete mode 100644 website/versioned_docs/version-0.77.0/auth_auth_module.md delete mode 100644 website/versioned_docs/version-0.77.0/auth_auth_provider.md delete mode 100644 website/versioned_docs/version-0.77.0/auth_index.md delete mode 100644 website/versioned_docs/version-0.77.0/config_entries_config_flow_handler.md delete mode 100644 website/versioned_docs/version-0.77.0/data_entry_flow_index.md delete mode 100644 website/versioned_docs/version-0.77.0/external_api_rest_python.md delete mode 100644 website/versioned_docs/version-0.77.0/frontend_data.md delete mode 100644 website/versioned_docs/version-0.78.0/asyncio_working_with_async.md delete mode 100644 website/versioned_docs/version-0.78.0/auth_api.md delete mode 100644 website/versioned_docs/version-0.78.0/auth_auth_module.md delete mode 100644 website/versioned_docs/version-0.78.0/auth_index.md delete mode 100644 website/versioned_docs/version-0.78.0/creating_component_code_review.md delete mode 100644 website/versioned_docs/version-0.78.0/development_guidelines.md delete mode 100644 website/versioned_docs/version-0.78.0/device_registry_index.md delete mode 100644 website/versioned_docs/version-0.78.0/documentation_standards.md delete mode 100644 website/versioned_docs/version-0.78.0/external_api_websocket.md delete mode 100644 website/versioned_docs/version-0.78.0/frontend_add_more_info.md delete mode 100644 website/versioned_docs/version-0.78.0/frontend_external_auth.md delete mode 100644 website/versioned_docs/version-0.78.0/hassio_addon_communication.md delete mode 100644 website/versioned_docs/version-0.78.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.78.0/hassio_addon_security.md delete mode 100644 website/versioned_docs/version-0.79.0/creating_component_code_review.md delete mode 100644 website/versioned_docs/version-0.79.0/creating_platform_code_review.md delete mode 100644 website/versioned_docs/version-0.79.0/development_environment.md delete mode 100644 website/versioned_docs/version-0.79.0/documentation_create_page.md delete mode 100644 website/versioned_docs/version-0.79.0/documentation_index.md delete mode 100644 website/versioned_docs/version-0.79.0/hassio_addon_communication.md delete mode 100644 website/versioned_docs/version-0.79.0/hassio_hass.md delete mode 100644 website/versioned_docs/version-0.79.0/integration_quality_scale_index.md delete mode 100644 website/versioned_docs/version-0.80.0/auth_index.md delete mode 100644 website/versioned_docs/version-0.80.0/auth_permissions.md delete mode 100644 website/versioned_docs/version-0.80.0/development_catching_up.md delete mode 100644 website/versioned_docs/version-0.80.0/development_environment.md delete mode 100644 website/versioned_docs/version-0.80.0/development_submitting.md delete mode 100644 website/versioned_docs/version-0.80.0/development_testing.md delete mode 100644 website/versioned_docs/version-0.80.0/documentation_create_page.md delete mode 100644 website/versioned_docs/version-0.80.0/documentation_index.md delete mode 100644 website/versioned_docs/version-0.80.0/documentation_standards.md delete mode 100644 website/versioned_docs/version-0.80.0/entity_sensor.md delete mode 100644 website/versioned_docs/version-0.80.0/entity_water_heater.md delete mode 100644 website/versioned_docs/version-0.80.0/frontend_architecture.md delete mode 100644 website/versioned_docs/version-0.80.0/hassio_addon_communication.md delete mode 100644 website/versioned_docs/version-0.80.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.80.0/hassio_addon_security.md delete mode 100644 website/versioned_docs/version-0.80.0/hassio_debugging.md delete mode 100644 website/versioned_docs/version-0.80.0/integration_quality_scale_index.md delete mode 100644 website/versioned_docs/version-0.81.0/asyncio_index.md delete mode 100644 website/versioned_docs/version-0.81.0/auth_api.md delete mode 100644 website/versioned_docs/version-0.81.0/auth_auth_module.md delete mode 100644 website/versioned_docs/version-0.81.0/development_index.md delete mode 100644 website/versioned_docs/version-0.81.0/development_testing.md delete mode 100644 website/versioned_docs/version-0.81.0/documentation_index.md delete mode 100644 website/versioned_docs/version-0.81.0/external_api_rest.md delete mode 100644 website/versioned_docs/version-0.81.0/external_api_server_sent_events.md delete mode 100644 website/versioned_docs/version-0.81.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.82.0/architecture_hassio.md delete mode 100644 website/versioned_docs/version-0.82.0/asyncio_working_with_async.md delete mode 100644 website/versioned_docs/version-0.82.0/auth_permissions.md delete mode 100644 website/versioned_docs/version-0.82.0/config_entries_index.md delete mode 100644 website/versioned_docs/version-0.82.0/creating_component_code_review.md delete mode 100644 website/versioned_docs/version-0.82.0/creating_component_deps_and_reqs.md delete mode 100644 website/versioned_docs/version-0.82.0/creating_component_generic_discovery.md delete mode 100644 website/versioned_docs/version-0.82.0/development_checklist.md delete mode 100644 website/versioned_docs/version-0.82.0/development_guidelines.md delete mode 100644 website/versioned_docs/version-0.82.0/development_validation.md delete mode 100644 website/versioned_docs/version-0.82.0/documentation_index.md delete mode 100644 website/versioned_docs/version-0.82.0/entity_registry_index.md delete mode 100644 website/versioned_docs/version-0.82.0/entity_sensor.md delete mode 100644 website/versioned_docs/version-0.82.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.82.0/hassio_addon_index.md delete mode 100644 website/versioned_docs/version-0.83.0/app_integration_index.md delete mode 100644 website/versioned_docs/version-0.83.0/app_integration_sending_data.md delete mode 100644 website/versioned_docs/version-0.83.0/app_integration_setup.md delete mode 100644 website/versioned_docs/version-0.83.0/app_integration_webview.md delete mode 100644 website/versioned_docs/version-0.83.0/auth_api.md delete mode 100644 website/versioned_docs/version-0.83.0/external_api_server_sent_events.md delete mode 100644 website/versioned_docs/version-0.83.0/hassio_addon_presentation.md delete mode 100644 website/versioned_docs/version-0.83.0/hassio_addon_publishing.md delete mode 100644 website/versioned_docs/version-0.84.0/creating_component_code_review.md delete mode 100644 website/versioned_docs/version-0.84.0/external_api_rest.md delete mode 100644 website/versioned_docs/version-0.85/asyncio_categorizing_functions.md delete mode 100644 website/versioned_docs/version-0.85/documentation_index.md delete mode 100644 website/versioned_docs/version-0.85/entity_air_pollutants.md delete mode 100644 website/versioned_docs/version-0.85/entity_sensor.md delete mode 100644 website/versioned_docs/version-0.85/external_api_rest.md delete mode 100644 website/versioned_docs/version-0.85/frontend_add_card.md delete mode 100644 website/versioned_docs/version-0.85/frontend_add_more_info.md delete mode 100644 website/versioned_docs/version-0.86.0/development_environment.md delete mode 100644 website/versioned_docs/version-0.86.0/documentation_index.md delete mode 100644 website/versioned_docs/version-0.86.0/entity_air_quality.md delete mode 100644 website/versioned_docs/version-0.86.0/external_api_rest.md delete mode 100644 website/versioned_docs/version-0.86.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.86.0/lovelace_custom_card.md delete mode 100644 website/versioned_docs/version-0.87.0/area_registry_index.md delete mode 100644 website/versioned_docs/version-0.87.0/development_environment.md delete mode 100644 website/versioned_docs/version-0.87.0/device_registry_index.md delete mode 100644 website/versioned_docs/version-0.87.0/documentation_create_page.md delete mode 100644 website/versioned_docs/version-0.87.0/documentation_standards.md delete mode 100644 website/versioned_docs/version-0.87.0/frontend_architecture.md delete mode 100644 website/versioned_docs/version-0.87.0/frontend_development.md delete mode 100644 website/versioned_docs/version-0.88.0/development_guidelines.md delete mode 100644 website/versioned_docs/version-0.88.0/entity_index.md delete mode 100644 website/versioned_docs/version-0.88.0/frontend_development.md delete mode 100644 website/versioned_docs/version-0.88.0/lovelace_custom_card.md delete mode 100644 website/versioned_docs/version-0.89.0/app_integration_index.md delete mode 100644 website/versioned_docs/version-0.89.0/app_integration_sending_data.md delete mode 100644 website/versioned_docs/version-0.89.0/app_integration_setup.md delete mode 100644 website/versioned_docs/version-0.89.0/auth_auth_module.md delete mode 100644 website/versioned_docs/version-0.89.0/config_entries_index.md delete mode 100644 website/versioned_docs/version-0.89.0/config_entries_options_flow_handler.md delete mode 100644 website/versioned_docs/version-0.89.0/creating_component_code_review.md delete mode 100644 website/versioned_docs/version-0.89.0/creating_platform_code_review.md delete mode 100644 website/versioned_docs/version-0.89.0/development_checklist.md delete mode 100644 website/versioned_docs/version-0.89.0/development_environment.md delete mode 100644 website/versioned_docs/version-0.89.0/device_registry_index.md delete mode 100644 website/versioned_docs/version-0.89.0/entity_alarm_control_panel.md delete mode 100644 website/versioned_docs/version-0.89.0/entity_cover.md delete mode 100644 website/versioned_docs/version-0.89.0/internationalization_translation.md delete mode 100644 website/versioned_docs/version-0.90.0/app_integration_sending_data.md delete mode 100644 website/versioned_docs/version-0.90.0/auth_permissions.md delete mode 100644 website/versioned_docs/version-0.90.0/config_entries_index.md delete mode 100644 website/versioned_docs/version-0.90.0/development_environment.md delete mode 100644 website/versioned_docs/version-0.90.0/device_registry_index.md delete mode 100644 website/versioned_docs/version-0.90.0/external_api_rest.md delete mode 100644 website/versioned_docs/version-0.90.0/external_api_websocket.md delete mode 100644 website/versioned_docs/version-0.90.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.90.0/hassio_addon_tutorial.md delete mode 100644 website/versioned_docs/version-0.90.0/maintenance.md delete mode 100644 website/versioned_docs/version-0.91.0/asyncio_working_with_async.md delete mode 100644 website/versioned_docs/version-0.91.0/creating_component_code_review.md delete mode 100644 website/versioned_docs/version-0.91.0/creating_platform_example_light.md delete mode 100644 website/versioned_docs/version-0.91.0/creating_platform_example_sensor.md delete mode 100644 website/versioned_docs/version-0.91.0/dev_101_events.md delete mode 100644 website/versioned_docs/version-0.91.0/entity_media_player.md delete mode 100644 website/versioned_docs/version-0.91.0/entity_sensor.md delete mode 100644 website/versioned_docs/version-0.91.0/integration_quality_scale_index.md delete mode 100644 website/versioned_docs/version-0.91.2/app_integration_notifications.md delete mode 100644 website/versioned_docs/version-0.91.2/app_integration_sending_data.md delete mode 100644 website/versioned_docs/version-0.91.2/app_integration_sensors.md delete mode 100644 website/versioned_docs/version-0.91.2/app_integration_setup.md delete mode 100644 website/versioned_docs/version-0.91.2/auth_auth_module.md delete mode 100644 website/versioned_docs/version-0.91.2/config_entries_config_flow_handler.md delete mode 100644 website/versioned_docs/version-0.91.2/config_entries_index.md delete mode 100644 website/versioned_docs/version-0.91.2/config_entries_options_flow_handler.md delete mode 100644 website/versioned_docs/version-0.91.2/creating_component_code_review.md delete mode 100644 website/versioned_docs/version-0.91.2/creating_component_deps_and_reqs.md delete mode 100644 website/versioned_docs/version-0.91.2/creating_component_generic_discovery.md delete mode 100644 website/versioned_docs/version-0.91.2/creating_component_index.md delete mode 100644 website/versioned_docs/version-0.91.2/creating_integration_file_structure.md delete mode 100644 website/versioned_docs/version-0.91.2/creating_integration_manifest.md delete mode 100644 website/versioned_docs/version-0.91.2/creating_platform_code_review.md delete mode 100644 website/versioned_docs/version-0.91.2/creating_platform_example_light.md delete mode 100644 website/versioned_docs/version-0.91.2/creating_platform_example_sensor.md delete mode 100644 website/versioned_docs/version-0.91.2/creating_platform_index.md delete mode 100644 website/versioned_docs/version-0.91.2/dev_101_services.md delete mode 100644 website/versioned_docs/version-0.91.2/dev_101_states.md delete mode 100644 website/versioned_docs/version-0.91.2/development_checklist.md delete mode 100644 website/versioned_docs/version-0.91.2/development_guidelines.md delete mode 100644 website/versioned_docs/version-0.91.2/development_index.md delete mode 100644 website/versioned_docs/version-0.91.2/development_validation.md delete mode 100644 website/versioned_docs/version-0.91.2/entity_sensor.md delete mode 100644 website/versioned_docs/version-0.91.2/internationalization_translation.md delete mode 100644 website/versioned_docs/version-0.91.2/maintenance.md delete mode 100644 website/versioned_docs/version-0.92.0/app_integration_setup.md delete mode 100644 website/versioned_docs/version-0.92.0/auth_auth_module.md delete mode 100644 website/versioned_docs/version-0.92.0/creating_integration_manifest.md delete mode 100644 website/versioned_docs/version-0.92.0/creating_platform_index.md delete mode 100644 website/versioned_docs/version-0.92.0/development_submitting.md delete mode 100644 website/versioned_docs/version-0.92.0/entity_climate.md delete mode 100644 website/versioned_docs/version-0.92.0/entity_fan.md delete mode 100644 website/versioned_docs/version-0.92.0/entity_media_player.md delete mode 100644 website/versioned_docs/version-0.92.0/entity_registry_index.md delete mode 100644 website/versioned_docs/version-0.92.0/external_api_websocket.md delete mode 100644 website/versioned_docs/version-0.92.0/hassio_addon_communication.md delete mode 100644 website/versioned_docs/version-0.92.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.92.0/hassio_addon_index.md delete mode 100644 website/versioned_docs/version-0.92.0/hassio_addon_presentation.md delete mode 100644 website/versioned_docs/version-0.92.0/hassio_addon_publishing.md delete mode 100644 website/versioned_docs/version-0.92.0/hassio_addon_security.md delete mode 100644 website/versioned_docs/version-0.92.0/hassio_addon_testing.md delete mode 100644 website/versioned_docs/version-0.92.0/hassio_debugging.md delete mode 100644 website/versioned_docs/version-0.92.0/hassio_hass.md delete mode 100644 website/versioned_docs/version-0.92.1/creating_integration_manifest.md delete mode 100644 website/versioned_docs/version-0.92.1/development_checklist.md delete mode 100644 website/versioned_docs/version-0.92.1/entity_fan.md delete mode 100644 website/versioned_docs/version-0.92.1/entity_light.md delete mode 100644 website/versioned_docs/version-0.92.1/entity_media_player.md delete mode 100644 website/versioned_docs/version-0.92.1/internationalization_custom_component_localization.md delete mode 100644 website/versioned_docs/version-0.93.0/auth_permissions.md delete mode 100644 website/versioned_docs/version-0.93.0/creating_integration_manifest.md delete mode 100644 website/versioned_docs/version-0.93.0/development_testing.md delete mode 100644 website/versioned_docs/version-0.93.0/documentation_create_page.md delete mode 100644 website/versioned_docs/version-0.93.0/entity_index.md delete mode 100644 website/versioned_docs/version-0.93.0/entity_media_player.md delete mode 100644 website/versioned_docs/version-0.93.0/entity_registry_index.md delete mode 100644 website/versioned_docs/version-0.93.0/entity_switch.md delete mode 100644 website/versioned_docs/version-0.93.0/hassio_addon_index.md delete mode 100644 website/versioned_docs/version-0.93.0/hassio_addon_security.md delete mode 100644 website/versioned_docs/version-0.93.0/hassio_debugging.md delete mode 100644 website/versioned_docs/version-0.94.0/config_entries_config_flow_handler.md delete mode 100644 website/versioned_docs/version-0.94.0/creating_component_code_review.md delete mode 100644 website/versioned_docs/version-0.94.0/creating_component_index.md delete mode 100644 website/versioned_docs/version-0.94.0/creating_integration_manifest.md delete mode 100644 website/versioned_docs/version-0.94.0/creating_platform_code_review.md delete mode 100644 website/versioned_docs/version-0.94.0/data_entry_flow_index.md delete mode 100644 website/versioned_docs/version-0.94.0/device_registry_index.md delete mode 100644 website/versioned_docs/version-0.94.0/entity_cover.md delete mode 100644 website/versioned_docs/version-0.94.0/external_api_rest.md delete mode 100644 website/versioned_docs/version-0.94.0/frontend_creating_custom_panels.md delete mode 100644 website/versioned_docs/version-0.94.0/frontend_creating_custom_ui.md delete mode 100644 website/versioned_docs/version-0.94.0/frontend_external_bus.md delete mode 100644 website/versioned_docs/version-0.94.0/hassio_addon_communication.md delete mode 100644 website/versioned_docs/version-0.94.0/hassio_debugging.md delete mode 100644 website/versioned_docs/version-0.95.0/config_entries_config_flow_handler.md delete mode 100644 website/versioned_docs/version-0.95.0/development_environment.md delete mode 100644 website/versioned_docs/version-0.95.0/development_testing.md delete mode 100644 website/versioned_docs/version-0.95.0/device_registry_index.md delete mode 100644 website/versioned_docs/version-0.95.0/documentation_standards.md delete mode 100644 website/versioned_docs/version-0.95.0/frontend_development.md delete mode 100644 website/versioned_docs/version-0.95.0/hassio_addon_tutorial.md delete mode 100644 website/versioned_docs/version-0.95.0/hassio_debugging.md delete mode 100644 website/versioned_docs/version-0.96.0/asyncio_categorizing_functions.md delete mode 100644 website/versioned_docs/version-0.96.0/development_environment.md delete mode 100644 website/versioned_docs/version-0.96.0/documentation_create_page.md delete mode 100644 website/versioned_docs/version-0.96.0/documentation_index.md delete mode 100644 website/versioned_docs/version-0.96.0/documentation_standards.md delete mode 100644 website/versioned_docs/version-0.96.0/entity_climate.md delete mode 100644 website/versioned_docs/version-0.96.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.97.0/creating_integration_manifest.md delete mode 100644 website/versioned_docs/version-0.97.0/external_api_websocket.md delete mode 100644 website/versioned_docs/version-0.98.0/config_entries_config_flow_handler.md delete mode 100644 website/versioned_docs/version-0.98.0/config_entries_options_flow_handler.md delete mode 100644 website/versioned_docs/version-0.98.0/creating_component_generic_discovery.md delete mode 100644 website/versioned_docs/version-0.98.0/development_environment.md delete mode 100644 website/versioned_docs/version-0.98.0/development_guidelines.md delete mode 100644 website/versioned_docs/version-0.98.0/entity_index.md delete mode 100644 website/versioned_docs/version-0.98.0/entity_registry_disabled_by.md delete mode 100644 website/versioned_docs/version-0.98.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.98.0/hassio_addon_tutorial.md delete mode 100644 website/versioned_docs/version-0.99.0/creating_component_index.md delete mode 100644 website/versioned_docs/version-0.99.0/dev_101_states.md delete mode 100644 website/versioned_docs/version-0.99.0/development_checklist.md delete mode 100644 website/versioned_docs/version-0.99.0/entity_weather.md delete mode 100644 website/versioned_docs/version-0.99.0/hassio_addon_config.md delete mode 100644 website/versioned_docs/version-0.99.0/lovelace_custom_card.md delete mode 100644 website/versioned_docs/version-0.99.3/device_automation_action.md delete mode 100644 website/versioned_docs/version-0.99.3/device_automation_condition.md delete mode 100644 website/versioned_docs/version-0.99.3/device_automation_index.md delete mode 100644 website/versioned_docs/version-0.99.3/device_automation_trigger.md delete mode 100644 website/versioned_docs/version-0.99.3/reproduce_state_index.md delete mode 100644 website/versioned_sidebars/version-0.101.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.105.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.72-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.73.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.74.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.76.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.77.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.78.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.79.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.80.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.83.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.87.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.89.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.91.2-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.94.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.98.0-sidebars.json delete mode 100644 website/versioned_sidebars/version-0.99.3-sidebars.json delete mode 100644 website/versions.json create mode 100644 yarn.lock diff --git a/.gitignore b/.gitignore index 35a442bc..b2d6de30 100644 --- a/.gitignore +++ b/.gitignore @@ -1,14 +1,20 @@ +# Dependencies +/node_modules + +# Production +/build + +# Generated files +.docusaurus +.cache-loader + +# Misc .DS_Store +.env.local +.env.development.local +.env.test.local +.env.production.local -node_modules - -lib/core/metadata.js -lib/core/MetadataBlog.js - -website/translated_docs -website/build/ -website/yarn.lock -website/package-lock.json -website/node_modules -website/i18n/* -!website/i18n/en.json +npm-debug.log* +yarn-debug.log* +yarn-error.log* diff --git a/.nvmrc b/.nvmrc index 45a4fb75..b009dfb9 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -8 +lts/* diff --git a/website/blog/2018-05-22-custom-ui-panels-api.md b/blog/2018-05-22-custom-ui-panels-api.md similarity index 100% rename from website/blog/2018-05-22-custom-ui-panels-api.md rename to blog/2018-05-22-custom-ui-panels-api.md diff --git a/website/blog/2018-06-01-071-custom-panels.md b/blog/2018-06-01-071-custom-panels.md similarity index 97% rename from website/blog/2018-06-01-071-custom-panels.md rename to blog/2018-06-01-071-custom-panels.md index cf9fed0d..ddd4ad61 100644 --- a/website/blog/2018-06-01-071-custom-panels.md +++ b/blog/2018-06-01-071-custom-panels.md @@ -3,7 +3,7 @@ author: Paulus Schoutsen authorURL: https://twitter.com/balloob authorImageURL: /img/profile/paulus.jpg authorTwitter: balloob -title: 0.71: Improved custom panels and minor changes for custom UI +title: "0.71: Improved custom panels and minor changes for custom UI" --- Efforts to modernize and localize the frontend are moving full speed. This blog post will touch upon the upcoming features for Home Assistant 0.71 which should hit the beta channel today and is planned for a release a week from now. diff --git a/website/blog/2018-07-02-trying-new-auth.md b/blog/2018-07-02-trying-new-auth.md similarity index 100% rename from website/blog/2018-07-02-trying-new-auth.md rename to blog/2018-07-02-trying-new-auth.md diff --git a/website/blog/2018-08-13-deprecating-remote-package.md b/blog/2018-08-13-deprecating-remote-package.md similarity index 100% rename from website/blog/2018-08-13-deprecating-remote-package.md rename to blog/2018-08-13-deprecating-remote-package.md diff --git a/website/blog/2019-02-19-the-great-migration.md b/blog/2019-02-19-the-great-migration.md similarity index 100% rename from website/blog/2019-02-19-the-great-migration.md rename to blog/2019-02-19-the-great-migration.md diff --git a/website/blog/2019-03-11-user-permissions.md b/blog/2019-03-11-user-permissions.md similarity index 100% rename from website/blog/2019-03-11-user-permissions.md rename to blog/2019-03-11-user-permissions.md diff --git a/website/blog/2019-04-12-new-integration-structure.md b/blog/2019-04-12-new-integration-structure.md similarity index 100% rename from website/blog/2019-04-12-new-integration-structure.md rename to blog/2019-04-12-new-integration-structure.md diff --git a/website/blog/2019-05-22-internet-of-things-and-the-modern-web.md b/blog/2019-05-22-internet-of-things-and-the-modern-web.md similarity index 96% rename from website/blog/2019-05-22-internet-of-things-and-the-modern-web.md rename to blog/2019-05-22-internet-of-things-and-the-modern-web.md index c1885b4d..21f87827 100644 --- a/website/blog/2019-05-22-internet-of-things-and-the-modern-web.md +++ b/blog/2019-05-22-internet-of-things-and-the-modern-web.md @@ -6,37 +6,13 @@ authorTwitter: balloob title: Internet of Things and the Modern Web --- - +import DiscussionBox from '../static/js/discourse_discussion.jsx' [Home Assistant](https://www.home-assistant.io) is world's biggest open-source home automation platform. It [supports](https://www.home-assistant.io/components/) over 1000 devices and services, and it is used everywhere: homes, [boats](https://hasspodcast.io/ha048/) and [museums](https://twitter.com/sjvanterpool/status/1124035433212649475). Today I want to talk about our UI, what we're trying to solve and how we solve it. Before we dive into why, what and how, let's take a look at our user interface. This is an embedded version of our demo, which is fully interactive. - +

The embedded demo has been hidden because the screen is too small. Open the demo in a new screen.

@@ -125,14 +101,9 @@ We do a lot of cool things, but the work is never done. Here are some challenges * **Stop using local storage.** We use local storage to store the auth tokens, the language preference and if the sidebar is shown. Since local storage is accessed synchronously, the browser will stop executing anything on the page while it is waiting for the local storage to be read from disk. Browser vendors are working on alternatives like [kv-storage](https://github.com/WICG/kv-storage) which are asynchronously and might become a viable alternative. * **Swap out Paper elements for [Material Web Components](https://github.com/material-components/material-components-web-components).** The Paper elements are no longer maintained and Material Web Components will be the successor, however they are still under development. The MWC components use Lit Element under the hood and rely on the material.io VanillaJS implementation of Material design. This means that they will be a lot lighter than the current Paper elements and will actually be maintained. +## Comments +
- + diff --git a/website/blog/2019-07-03-climate-cleanup.md b/blog/2019-07-03-climate-cleanup.md similarity index 87% rename from website/blog/2019-07-03-climate-cleanup.md rename to blog/2019-07-03-climate-cleanup.md index 1a67274b..a5a8e6eb 100644 --- a/website/blog/2019-07-03-climate-cleanup.md +++ b/blog/2019-07-03-climate-cleanup.md @@ -6,6 +6,8 @@ authorTwitter: balloob title: Climate Cleanup --- +import DiscussionBox from '../static/js/discourse_discussion.jsx' + _This post is about the upcoming changes for the Home Assistant climate integration. These changes are being implemented right now and are no longer up for discussion. If you want to see changes, consider opening [an architecture issue](https://github.com/home-assistant/architecture/issues)._ Starting with Home Assistant 0.96, we're shipping a big architectural clean up of our climate integrations. This effort is lead by Pascal Vizeli. @@ -34,14 +36,9 @@ If you are a maintainer of an integration that has a climate platform or maintai +## Comments +
- + diff --git a/website/blog/2019-07-19-building-all-the-things.md b/blog/2019-07-19-building-all-the-things.md similarity index 94% rename from website/blog/2019-07-19-building-all-the-things.md rename to blog/2019-07-19-building-all-the-things.md index e7046b89..e04ee011 100644 --- a/website/blog/2019-07-19-building-all-the-things.md +++ b/blog/2019-07-19-building-all-the-things.md @@ -6,6 +6,8 @@ authorTwitter: balloob title: Building All The Things --- +import DiscussionBox from '../static/js/discourse_discussion.jsx' + _How Home Assistant is using Azure Pipelines to automate all the things._ Here at Home Assistant, we love automation! Not only in our homes, but also when doing development work. We do a release every three weeks and it includes code from over 80 different people. All is managed by only two people working on this full-time (thanks [Nabu Casa](https://www.nabucasa.com)!). @@ -46,7 +48,7 @@ CircleCI had a nice feature that it could distribute your tests over multiple wo With Azure, we get more runners which are more powerful and faster, but no parallelization. This means that an individual build will take longer, however, with many builds coming in, the individual build time remains roughly the same, as we are not experiencing any backlog.
-![Screenshot of the Home Assistant CI pipeline.](/img/en/blog/2019-07-building-all-the-things/test-results.png)
+![Screenshot of the Home Assistant CI pipeline.](/img/en/blog/2019-07-building-all-the-things/test-results.png)
Screenshot of the [test results](https://dev.azure.com/home-assistant/Home%20Assistant/_build/results?buildId=3976&view=ms.vss-test-web.build-test-results-tab).
@@ -59,7 +61,7 @@ The Azure Pipelines agents are using the amd64 CPU architecture. It is possible We use a feature on Azure Pipelines called [self-hosted agents](https://docs.microsoft.com/en-us/azure/devops/pipelines/agents/agents?view=azure-devops#install) to host build agents on our own hardware with the right architecture. Azure Pipelines manages the pipeline definition and the orchestration, but the execution runs blazing fast on our own hardware.
-![Screenshot of the Home Assistant CI pipeline.](/img/en/blog/2019-07-building-all-the-things/build-cabinet.jpg)
+![Screenshot of the Home Assistant CI pipeline.](/img/en/blog/2019-07-building-all-the-things/build-cabinet.jpg)
Our build cabinet.
@@ -102,14 +104,9 @@ Building out a wide range of automations has really helped Home Assistant scale - [Home Assistant on Azure Pipelines](https://dev.azure.com/home-assistant/Home%20Assistant/_build) - [Hass.io on Azure Pipelines](https://dev.azure.com/home-assistant/Hass.io/_build) +## Comments +
- + diff --git a/website/blog/2019-07-31-black.md b/blog/2019-07-31-black.md similarity index 100% rename from website/blog/2019-07-31-black.md rename to blog/2019-07-31-black.md diff --git a/website/blog/2019-09-27-hacktoberfest.md b/blog/2019-09-27-hacktoberfest.md similarity index 91% rename from website/blog/2019-09-27-hacktoberfest.md rename to blog/2019-09-27-hacktoberfest.md index e61d1de7..9286b565 100644 --- a/website/blog/2019-09-27-hacktoberfest.md +++ b/blog/2019-09-27-hacktoberfest.md @@ -6,6 +6,8 @@ authorTwitter: balloob title: Hacktoberfest 2019 --- +import DiscussionBox from '../static/js/discourse_discussion.jsx' + This year we're again participating in [Hacktoberfest](https://hacktoberfest.digitalocean.com). Hacktoberfest is a worldwide event to celebrate open source. If you make four pull request in the month of October, you'll get a free Hacktoberfest t-shirt. Home Assistant is currently racing towards our magical 1.0 release. Home Assistant 1.0 is all about user friendliness. As part of this, we have recently introduced device automations and are expanding how scenes work in Home Assistant. @@ -69,14 +71,10 @@ For Hacktoberfest, let's see if we can expand the number of supported types! To - [Documentation on how to run tests](https://almond.stanford.edu/doc/thingpedia-testing.md) - Run Almond at [home](https://github.com/stanford-oval/almond-server), use [the Android version](https://play.google.com/store/apps/details?id=edu.stanford.thingengine.engine&hl=en_US) or [the Gnome version](https://flathub.org/apps/details/edu.stanford.Almond) + +## Comments +
- + diff --git a/website/blog/2019-10-05-simple-mode.md b/blog/2019-10-05-simple-mode.md similarity index 90% rename from website/blog/2019-10-05-simple-mode.md rename to blog/2019-10-05-simple-mode.md index 0f25bd68..54a34b8f 100644 --- a/website/blog/2019-10-05-simple-mode.md +++ b/blog/2019-10-05-simple-mode.md @@ -6,6 +6,8 @@ authorTwitter: balloob title: Simple Mode in Home Assistant 1.0 --- +import DiscussionBox from '../static/js/discourse_discussion.jsx' + > This blog post references simple and advanced mode. This has since been renamed to standard mode and advanced mode. The Home Assistant UI has two different modes. There is a simple mode and an advanced mode. Simple mode has been introduced recently in [Home Assistant 0.96](https://www.home-assistant.io/blog/2019/07/17/release-96/#advanced-mode). In this post I want to outline my vision for simple mode in Home Assistant 1.0. @@ -84,12 +86,5 @@ Another ongoing effort that will make it easier for everyone is our Hacktoberfes
- + diff --git a/website/blog/2020-02-04-new-zwave.md b/blog/2020-02-04-new-zwave.md similarity index 78% rename from website/blog/2020-02-04-new-zwave.md rename to blog/2020-02-04-new-zwave.md index f1017bc2..a97c8de5 100644 --- a/website/blog/2020-02-04-new-zwave.md +++ b/blog/2020-02-04-new-zwave.md @@ -6,6 +6,8 @@ authorTwitter: balloob title: Update on the Z-Wave integration --- +import DiscussionBox from '../static/js/discourse_discussion.jsx' + At the State of the Union we [introduced that we're working on a new Z-Wave integration](https://youtu.be/tc17q1Zn0Xs?t=4482). It's based on a new project by the Open Z-Wave project called [OZWDaemon](https://github.com/OpenZWave/qt-openzwave) and we will communicate with it over MQTT. This new approach allows us to integrate directly with the core of Open Z-Wave without relying on bindings via other languages. This allows us to easily keep up to date with the latest Open Z-Wave versions. @@ -25,12 +27,5 @@ Once the integration is mature enough, it will become part of Home Assistant Cor
- + diff --git a/crowdin.yaml b/crowdin.yaml deleted file mode 100644 index 74211510..00000000 --- a/crowdin.yaml +++ /dev/null @@ -1,53 +0,0 @@ -project_identifier_env: CROWDIN_DOCUSAURUS_PROJECT_ID -api_key_env: CROWDIN_DOCUSAURUS_API_KEY -base_path: "./" -preserve_hierarchy: true - -files: - - - source: '/docs/*.md' - translation: '/website/translated_docs/%locale%/%original_file_name%' - languages_mapping: &anchor - locale: - 'af': 'af' - 'ar': 'ar' - 'bs-BA': 'bs-BA' - 'ca': 'ca' - 'cs': 'cs' - 'da': 'da' - 'de': 'de' - 'el': 'el' - 'es-ES': 'es-ES' - 'fa': 'fa-IR' - 'fi': 'fi' - 'fr': 'fr' - 'he': 'he' - 'hu': 'hu' - 'id': 'id-ID' - 'it': 'it' - 'ja': 'ja' - 'ko': 'ko' - 'mr': 'mr-IN' - 'nl': 'nl' - 'no': 'no-NO' - 'pl': 'pl' - 'pt-BR': 'pt-BR' - 'pt-PT': 'pt-PT' - 'ro': 'ro' - 'ru': 'ru' - 'sk': 'sk-SK' - 'sr': 'sr' - 'sv-SE': 'sv-SE' - 'tr': 'tr' - 'uk': 'uk' - 'vi': 'vi' - 'zh-CN': 'zh-CN' - 'zh-TW': 'zh-TW' - - - source: '/website/i18n/en.json' - translation: '/website/i18n/%locale%.json' - languages_mapping: *anchor - #- - # source: '/website/versioned_docs/**/*.md' - # translation: '/website/translated_docs/%locale%/**/%original_file_name%' - # languages_mapping: *anchor diff --git a/docs/architecture_components.md b/docs/architecture_components.md index f4c2279d..dabc0804 100644 --- a/docs/architecture_components.md +++ b/docs/architecture_components.md @@ -5,7 +5,9 @@ sidebar_label: "Components" Home Assistant can be extended with **components**. Each component is responsible for a specific domain within Home Assistant. Components can listen for or trigger events, offer services, and maintain states. Components are written in Python and can do all the goodness that Python has to offer. Out of the box, Home Assistant offers a bunch of [built-in components](https://www.home-assistant.io/components/). -Diagram showing interaction between components and the Home Assistant core. + There are two types of components within Home Assistant: components that interact with an Internet of Things domain, and components that respond to events that happen within Home Assistant. Read on to learn about each type! @@ -45,7 +47,7 @@ In the event of the sun setting: When we put all the different pieces of Home Assistant together, it's a close match for the initial home automation overview sketch. The smart home AI has not been implemented yet, so it's not included in this picture. -Overview of the full Home Assistant architecture with a couple of loaded components and platforms diff --git a/docs/architecture_entities.md b/docs/architecture_entities.md index 67b8ee3b..7168c5da 100644 --- a/docs/architecture_entities.md +++ b/docs/architecture_entities.md @@ -3,7 +3,9 @@ title: "Entity Architecture" sidebar_label: Entity --- -![Architecture overview of Hass.io](/img/en/architecture/entities_architecture.png) +Architecture Overview of Home Assistant ## Configuration diff --git a/docs/architecture_hassio.md b/docs/architecture_hassio.md index 9b421975..3debeaa0 100644 --- a/docs/architecture_hassio.md +++ b/docs/architecture_hassio.md @@ -3,7 +3,8 @@ title: "Hass.io Architecture" sidebar_label: Hass.io --- -![Architecture overview of Hass.io](/img/en/architecture/hassio.png) +Architecture Overview of Home Assistant ## Host Control (HC) diff --git a/docs/architecture_index.md b/docs/architecture_index.md index c441b6f8..6aa638c8 100644 --- a/docs/architecture_index.md +++ b/docs/architecture_index.md @@ -11,7 +11,7 @@ For more information about each part in this overview, @@ -23,7 +23,7 @@ The Home Assistant core is responsible for Home Control. Home Assistant contains * **Service Registry**: listens on the event bus for `call_service` events and allows other code to register services. * **Timer**: sends a `time_changed` event every 1 second on the event bus. -Overview of the Home Assistant core architecture diff --git a/docs/auth_api.md b/docs/auth_api.md index a84a4b81..95410a13 100644 --- a/docs/auth_api.md +++ b/docs/auth_api.md @@ -25,8 +25,9 @@ If you require a different redirect url (ie, if building a native app), you can Home Assistant will scan the first 10kB of a website for link tags. ## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) + +Overview of how the different parts interact + > All example URLs here are shown with extra spaces and new lines for display purposes only. diff --git a/docs/auth_auth_module.md b/docs/auth_auth_module.md index f19c7f70..3f83f75a 100644 --- a/docs/auth_auth_module.md +++ b/docs/auth_auth_module.md @@ -36,7 +36,8 @@ Each MFA module need to implement a setup flow handler extends from `mfa_modules ## Workflow -![Multi Factor Authentication Workflow](/img/en/auth/mfa_workflow.png) +Multi Factor Authentication Workflow + logo-pretty + Created with Sketch. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/website/static/img/logo-responsive.svg b/static/img/logo-responsive.svg similarity index 100% rename from website/static/img/logo-responsive.svg rename to static/img/logo-responsive.svg diff --git a/website/static/img/logo-white.svg b/static/img/logo-white.svg similarity index 100% rename from website/static/img/logo-white.svg rename to static/img/logo-white.svg diff --git a/static/img/logo.svg b/static/img/logo.svg new file mode 100644 index 00000000..9db6d0d0 --- /dev/null +++ b/static/img/logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/website/static/img/profile/paulus.jpg b/static/img/profile/paulus.jpg similarity index 100% rename from website/static/img/profile/paulus.jpg rename to static/img/profile/paulus.jpg diff --git a/static/img/undraw_docusaurus_mountain.svg b/static/img/undraw_docusaurus_mountain.svg new file mode 100644 index 00000000..431cef2f --- /dev/null +++ b/static/img/undraw_docusaurus_mountain.svg @@ -0,0 +1,170 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/img/undraw_docusaurus_react.svg b/static/img/undraw_docusaurus_react.svg new file mode 100644 index 00000000..e4170504 --- /dev/null +++ b/static/img/undraw_docusaurus_react.svg @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/static/img/undraw_docusaurus_tree.svg b/static/img/undraw_docusaurus_tree.svg new file mode 100644 index 00000000..a05cc03d --- /dev/null +++ b/static/img/undraw_docusaurus_tree.svg @@ -0,0 +1 @@ +docu_tree \ No newline at end of file diff --git a/static/js/discourse_discussion.jsx b/static/js/discourse_discussion.jsx new file mode 100644 index 00000000..23efe577 --- /dev/null +++ b/static/js/discourse_discussion.jsx @@ -0,0 +1,112 @@ +import React from 'react'; +import PropTypes from 'prop-types'; + +export default class DiscussionBox extends React.Component { + + constructor(props) { + super(props); + this.postMessageReceived = this.postMessageReceived.bind(this); + } + + componentDidMount() { + this.DiscourseEmbed = { + discourseUrl: this.props.discourseUrl, + discourseEmbedUrl: this.props.discourseEmbedUrl, + }; + window.addEventListener('message', this.postMessageReceived, false); + } + + componentWillUnmount() { + window.removeEventListener('message', this.postMessageReceived); + } + + getIframeSource() { + const { discourseUrl, discourseEmbedUrl, discourseUserName } = this.props; + const queryParams = {}; + + if (discourseEmbedUrl) { + if (discourseEmbedUrl.indexOf('/') === 0) { + console.error('discourseEmbedUrl must be a full URL, not a relative path'); + } + + queryParams.embed_url = encodeURIComponent(discourseEmbedUrl); + } + + if (discourseUserName) { + queryParams.discourse_username = discourseUserName; + } + + let src = discourseUrl + 'embed/comments'; + const keys = Object.keys(queryParams); + if (keys.length > 0) { + src += '?'; + + for (let i = 0; i < keys.length; i++) { + if (i > 0) { src += '&'; } + + const k = keys[i]; + src += k + '=' + queryParams[k]; + } + } + + return src; + } + + postMessageReceived(e) { + if (!e) { return; } + + const iframe = this.iframe; + const { discourseUrl } = this.props; + + if (normalizeUrl(discourseUrl).indexOf(normalizeUrl(e.origin)) === -1) { return; } + + if (e.data) { + if (e.data.type === 'discourse-resize' && e.data.height) { + iframe.height = e.data.height + 'px'; + } + + if (e.data.type === 'discourse-scroll' && e.data.top) { + // find iframe offset + const destY = findPosY(iframe) + e.data.top; + window.scrollTo(0, destY); + } + } + } + + render() { + return ( +
+ -
diff --git a/website/translated_docs/nl/asyncio_categorizing_functions.md b/website/translated_docs/nl/asyncio_categorizing_functions.md deleted file mode 100644 index 71e8206d..00000000 --- a/website/translated_docs/nl/asyncio_categorizing_functions.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: "Categorizing Functions" ---- - -A piece of work within Home Assistant is represented by a function that will be invoked. It will either run inside our event loop or inside our thread pool, depending on if it is async safe. - -Home Assistant uses the convention that all functions that must be run from within the event loop are prefixed with `async_`. - -## The coroutine function - -Coroutines are special functions based on Python’s generators syntax which allows them to suspend execution while waiting on a result. - -Invoking a coroutine function will return a Generator object back, but will not actually begin execution. This object will execute the task when it is either yielded from (from within another coroutine) or it is scheduled on the event loop. - -To declare a function a coroutine, import the coroutine annotation from the asyncio package and annotate your function. - -```python -async def async_look_my_coroutine(target): - result = await entity.async_turn_on() - if result: - print("hello {}".format(target)) - -hass.loop.create_task(async_look_my_coroutine("world")) -``` - -In this example, we schedule the coroutine by calling `hass.loop.create_task`. This will add the coroutine to the queue of tasks to be run. When the event loop is running `async_look_my_coroutine` it will suspend the task when `await entity.async_turn_on()` is called. At that point a new task will be scheduled to execute `entity.async_turn_on()`. When that job has been executed, `async_look_my_coroutine` will resume. - -## The callback function - -This is a normal function that is considered safe to be run from within the event loop. A callback is unable to suspend itself and thus cannot do any I/O or call a coroutine. A callback is capable of scheduling a new task but it will not be able to wait for the results. - -To declare a function as a callback, import the callback annotation from the core package and annotate your function. - -A common use case for a callback in Home Assistant is as a listener for an event or a service call. It can process the incoming information and then schedule the right calls to be made. Example from the automation component. - -```python -from homeassistant.core import callback - -@callback -def async_trigger_service_handler(service_call): - """Handle automation trigger service calls.""" - vars = service_call.data.get(ATTR_VARIABLES) - for entity in component.async_extract_from_service(service_call): - hass.loop.create_task(entity.async_trigger(vars, True)) -``` - -In this example, `entity.async_trigger` is a coroutine function. Invoking the coroutine function will return a coroutine task. The passed in parameters will be used when the task gets executed. - -To execute the task we have to schedule it for execution on the event loop. This is done by calling `hass.loop.create_task`. - -### Why even have callbacks? - -You might wonder, if a coroutine can do everything a callback can do, why even have a callback. The reason is performance and better state consistency of the core API objects. - -When coroutine A waits for coroutine B, it will suspend itself and schedule a new task to run B. This means that the event loop is now running A, B and then A again. If B is a callback, A will never have to suspend itself and thus the event loop is just running A. The consistency implication is that other events queued to run on the event loop continue to wait until callbacks complete, but will be interleaved when yielding to another coroutine. - -## Event loop and thread safe - -These are functions that are safe to run both in a thread and inside the event loop. These functions are usually performing a computation or transform data in memory. Anything that does I/O does not fall under this category. Many standard library functions fall in this category. For example generating the sum of a set of numbers using sum or merging two dictionaries. - -There is no special annotation to mark functions as part of this category and care should be taken when using these functions from inside the event loop. When in doubt, look at their implementation. - -## Other functions - -These are all the functions that did not fit in the previous categories. These functions are either thread-safe or not considered safe to be run within the event loop. These are functions that use sleep, or perform I/O. - -There is no special annotation necessary to be considered part of this category. \ No newline at end of file diff --git a/website/translated_docs/nl/asyncio_index.md b/website/translated_docs/nl/asyncio_index.md deleted file mode 100644 index 6dd2ecaa..00000000 --- a/website/translated_docs/nl/asyncio_index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "Asynchronous Programming" -sidebar_label: Introduction ---- - -On September 29, 2016 we released [Home Assistant 0.29](https://www.home-assistant.io/blog/2016/09/29/async-sleepiq-emoncms-stocks/) as part of our bi-weekly release schedule. This release introduced a complete overhaul of the core spearheaded by [Ben Bangert](https://github.com/bbangert/). - -The old core was set up like a “traditional” threaded application. Each resource that was not thread safe (ie. the state of entities) would be protected by a lock. This caused a lot of waiting and potential inconsistency because a task could now end up waiting halfway through its job until some resource got freed. - -Our new core is based on Python’s built-in **asyncio** module. Instead of having all threads have access to the core API objects, access is now limited to a special thread called the *event loop*. All components will now schedule themselves as a task to be executed by the event loop. This gives us the guarantee that only a single task is executed at the same time, meaning we no longer need any locks. - -The only problem with running everything inside the event loop is when a task does blocking I/O; something most third-party Python libraries do. For example, while requesting new information from a device, the core will stop running until we get a response from the device. To handle this, a task is able to suspend itself until the response is available, after which it will be enqueued in the event loop to process the result. - -For a task to be able to suspend itself, all code that it calls must support this capability. In practice, this would mean that each device integration will need a full rewrite of the library that offers the integration! As this is something that cannot be achieved, ever, a 100% backwards compatible API has been added so that no platform will require updating. - -The backwards compatible API schedules a task in a different thread and blocks that thread until the task has been processed by the event loop. \ No newline at end of file diff --git a/website/translated_docs/nl/asyncio_working_with_async.md b/website/translated_docs/nl/asyncio_working_with_async.md deleted file mode 100644 index 6f56876c..00000000 --- a/website/translated_docs/nl/asyncio_working_with_async.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: "Working with Async" ---- - -Although we have a backwards compatible API, using the async core directly will be a lot faster. Most core components have already been rewritten to leverage the async core. This includes the EntityComponent helper (foundation of light, switch, etc), scripts, groups and automation. - -## Interacting with the core - -[All methods in the Home Assistant core](https://dev-docs.home-assistant.io/en/master/api/core.html) are implemented in two flavors: an async version and a version to be called from other threads. The versions for other are merely wrappers that call the async version in a threadsafe manner. - -So if you are making calls to the core (the hass object) from within a callback or coroutine, use the methods that start with async_. If you need to call an async_ function that is a coroutine, your task must also be a coroutine. - -## Implementing an async component - -To make a component async, implement an async_setup. - -```python -def setup(hass, config): - # Setup your component outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup(hass, config): - # Setup your component inside of the event loop. -``` - -## Implementing an async platform - -For platforms we support async setup. Instead of setup_platform you need to have a coroutine async_setup_platform. - -```python -setup_platform(hass, config, add_entities, discovery_info=None): - # Setup your platform outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup_platform(hass, config, async_add_entities, - discovery_info=None): - # Setup your platform inside of the event loop -``` - -The only difference with the original parameters is that the `add_entities` function has been replaced by the async friendly callback `async_add_entities`. - -## Implementing an async entity - -You can make your entity async friendly by converting your update method to be async. This requires the dependency of your entities to also be async friendly! - -```python -class MyEntity(Entity): - def update(self): - """Retrieve latest state.""" - self._state = fetch_state() -``` - -Will turn into: - -```python -class MyEntity(Entity): - async def async_update(self): - """Retrieve latest state.""" - self._state = await async_fetch_state() -``` - -Make sure that all properties defined on your entity do not result in I/O being done. All data has to be fetched inside the update method and cached on the entity. This is because these properties are read from within the event loop and thus doing I/O will result in the core of Home Assistant waiting until your I/O is done. - -## Calling async functions from threads - -Sometimes it will happen that you’re in a thread and you want to call a function that is only available as async. Home Assistant includes a few async helper utilities to help with this. - -In the following example, `say_hello` will schedule `async_say_hello` and block till the function has run and get the result back. - -```python -import asyncio - -def say_hello(hass, target): - return asyncio.run_coroutine_threadsafe( - async_say_hello(hass, target), hass.loop).result() - -async def async_say_hello(hass, target): - return "Hello {}!".format(target) -``` - -## Calling sync functions from async - -If you are running inside an async context, it might sometimes be necessary to call a sync function. Do this like this: - -```python -# hub.update() is a sync function. -result = await hass.async_add_executor_job(hub.update) -``` - -## Starting independent task from async - -If you want to spawn a task that will not block the current async context, you can choose to create it as a task on the event loop. It will then be executed in parallel. - -```python -hass.async_create_task(async_say_hello(hass, target)) -``` \ No newline at end of file diff --git a/website/translated_docs/nl/auth_api.md b/website/translated_docs/nl/auth_api.md deleted file mode 100644 index 0fa664fa..00000000 --- a/website/translated_docs/nl/auth_api.md +++ /dev/null @@ -1,245 +0,0 @@ ---- -title: "Authentication API" -sidebar_label: API ---- - -This page will describe the steps required for your application to authorize against and integrate with Home Assistant instances. [See a demo](https://hass-auth-demo.glitch.me) powered by our helper lib [home-assistant-js-websocket](https://github.com/home-assistant/home-assistant-js-websocket). - -Each user has their own instance of Home Assistant which gives each user control over their own data. However, we also wanted to make it easy for third party developers to create applications that allow users to integrate with Home Assistant. To achieve this, we have adopted the [OAuth 2 specification](https://tools.ietf.org/html/rfc6749) combined with the [OAuth 2 IndieAuth extension](https://indieauth.spec.indieweb.org/) for generating clients. - -## Clients - -Before you can ask the user to authorize their instance with your application, you will need a client. In traditional OAuth2, the server needs to generate a client before a user can authorize. However, as each server belongs to a user, we've adopted a slightly different approach from [IndieAuth](https://indieauth.spec.indieweb.org/#client-identifier). - -The client ID you need to use is the website of your application. The redirect url has to be of the same host and port as the client ID. For example: - -- client id: `https://www.my-application.io` -- redirect uri: `https://www.my-application.io/hass/auth_callback` - -If you require a different redirect url (ie, if building a native app), you can add an HTML tag to the content of the website of your application (the client ID) with an approved redirect url. For example, add this to your site to whitelist redirect uri `hass://auth`: - -```html - -``` - -Home Assistant will scan the first 10kB of a website for link tags. - -## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) - -> All example URLs here are shown with extra spaces and new lines for display purposes only. - -The authorize url should contain `client_id` and `redirect_uri` as query parameters. - - http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2F%3Fauth_callback%3D1 - - -Optionally you can also include a `state` parameter, this will be added to the redirect uri. The state is perfect to store the instance url that you are authenticating with. Example: - - http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2Fauth_callback& - state=http%3A%2F%2Fhassio.local%3A8123 - - -The user will navigate to this link and be presented with instructions to log in and authorize your application. Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code and state as part of the query parameters. Example: - - https://hass-auth-demo.glitch.me/auth_callback - code=12345& - state=http%3A%2F%2Fhassio.local%3A8123 - - -This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section). - -## Token - -The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. In thee case of refresh token, the token endpoint is also capable of revoking a token. - -All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`. - -### Authorization code - -> All requests to the token endpoint need to contain the exact same client ID as was used to redirect the user to the authorize endpoint. - -Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is: - - grant_type=authorization_code& - code=12345& - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me - - -The return response will be an access and refresh token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "refresh_token": "IJKLMNOPQRST", - "token_type": "Bearer" -} -``` - -The access token is a short lived token that can be used to access the API. The refresh token can be used to fetch new access tokens. The `expires_in` value is seconds that the access token is valid. - -An HTTP status code of 400 will be returned if an invalid request has been issued. The HTTP status code will be 403 if a token is requested for an inactive user. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Refresh token - -Once you have retrieved a refresh token via the grant type `authorization_code`, you can use it to fetch new access tokens. The request body is: - - grant_type=refresh_token& - refresh_token=IJKLMNOPQRST& - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me - - -The return response will be an access token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "token_type": "Bearer" -} -``` - -An HTTP status code of 400 will be returned if an invalid request has been issued. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Revoking a refresh token - -> client_id is not need for revoke refresh token - -The token endpoint is also capable of revoking a refresh token. Revoking a refresh token will immediately revoke the refresh token and all access tokens that it has ever granted. To revoke a refresh token, make the following request: - - token=IJKLMNOPQRST& - action=revoke - - -The request will always respond with an empty body and HTTP status 200, regardless if the request was successful. - -## Long-lived access token - -A long-lived access token is usually used for 3rd party API calls and webhook-ish integrations. To generate a long-lived access token, an active websocket connection has to be established. - -Send websocket command `auth/long_lived_access_token` will create a long-lived access token for current user. Access token will not be saved in Home Assistant. User need to record the token in secure place. - -```json -{ - "id": 11, - "type": "auth/long_lived_access_token", - "client_name": "GPS Logger", - "client_icon": null, - "lifespan": 365 -} -``` - -Result will be a long-lived access token: - -```json -{ - "id": 11, - "type": "result", - "success": true, - "result": "ABCDEFGH" -} -``` - -Additionally, a long-lived access token can be created using the UI tool located at the bottom of the user's Home Assistant profile page. - -## Making authenticated requests - -Once you have an access token, you can make authenticated requests to the Home Assistant APIs. - -For the websocket connection, pass the access token in the [authentication message](https://developers.home-assistant.io/docs/en/external_api_websocket.html#authentication-phase). - -For HTTP requests, pass the token type and access token as the authorization header: - - Authorization: Bearer ABCDEFGH - - -### Example: cURL - -```shell -curl -X GET \ - https://your.awesome.home/api/error/all \ - -H 'Authorization: Bearer ABCDEFGH' -``` - -### Example: Python - -```python -import requests - -url = "https://your.awesome.home/api/error/all" -headers = { - 'Authorization': "Bearer ABCDEFGH", -} -response = requests.request('GET', url, headers=headers) - -print(response.text) -``` - -### Example: NodeJS - -```JavaScript -fetch('https://your.awesome.home/api/error/all', { - headers: { Authorization: 'Bearer ABCDEFGH' } -}).then(function (response) { - if (!response.ok) { - return Promise.reject(response); - } - return response.text(); -}).then(function (body ) { - console.log(body); -}); -``` - -If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and so the user is no longer logged in. You should clear the user's data and ask the user to authorize again. - -## Signed paths - -Sometimes you want a user to make a GET request to Home Assistant to download data. In this case the normal auth system won't do, as we can't link the user to an API with the auth header attached to it. In that case, a signed path can help. - -A signed path is a normal path on our server, like `/api/states`, but with an attached secure authentication signature. The user is able to navigate to this path and will be authorised as the access token that created the signed path. Signed paths can be created via the websocket connection and are meant to be shortlived. The default expiration is 30 seconds. - -To get a signed path, send the following command: - -```js -{ - "type": "auth/sign_path", - "path": "/api/states", - // optional, expiration time in seconds. Defaults to 30 seconds - "expires": 20 -} -``` - -The response will contain the signed path: - -```js -{ - "path": "/api/states?authSig=ABCDEFGH" -} -``` - -Some things to note about a signed path: - -- If the refresh token is deleted, the signed url is no longer valid. -- If the user is deleted, the signed url is no longer valid (because the refresh token will be deleted). -- If Home Assistant is restarted, the signed url is no longer valid. -- Access is only validated when the request is received. If a response takes longer than the expiration time (ie, downloading a large file), the download will continue after the expiration date has passed. \ No newline at end of file diff --git a/website/translated_docs/nl/auth_auth_module.md b/website/translated_docs/nl/auth_auth_module.md deleted file mode 100644 index e0e000a7..00000000 --- a/website/translated_docs/nl/auth_auth_module.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: "Multi-factor Authentication Modules" ---- - -Multi-factor Authentication Modules are used in conjunction with [Authentication Provider](auth_auth_provider.html) to provide a fully configurable authentication framework. Each MFA module may provide one multi-factor authentication function. User can enable multiple mfa modules, but can only select one module in login process. - -## Defining an mfa auth module - -> We currently only support built-in mfa auth modules. Support for custom auth modules might arrive in the future. - -Multi-factor Auth modules are defined in `homeassistant/auth/mfa_modules/.py`. The auth module will need to provide an implementation of the `MultiFactorAuthModule` class. - -For an example of a fully implemented auth module, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/mfa_modules/insecure_example.py). - -Multi-factor Auth modules shall extend the following methods of `MultiFactorAuthModule` class. - -| method | Required | Description | -| ---------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -| `@property def input_schema(self)` | Yes | Return a schema defined the user input form. | -| `async def async_setup_flow(self, user_id)` | Yes | Return a SetupFlow to handle the setup workflow. | -| `async def async_setup_user(self, user_id, setup_data)` | Yes | Set up user for use this auth module. | -| `async def async_depose_user(self, user_id)` | Yes | Remove user information from this auth module. | -| `async def async_is_user_setup(self, user_id)` | Yes | Return whether user is set up. | -| `async def async_validate(self, user_id, user_input)` | Yes | Given a user_id and user input, return validation result. | -| `async def async_initialize_login_mfa_step(self, user_id)` | No | Will be called once before display the mfa step of login flow. This is not initialization for the MFA module but the mfa step in login flow. | - -## Setup Flow - -Before user can use a multi-factor auth module, it has to be enabled or set up. All available modules will be listed in user profile page, user can enable the module he/she wants to use. A setup data entry flow will guide user finish the necessary steps. - -Each MFA module need to implement a setup flow handler extends from `mfa_modules.SetupFlow` (if only one simple setup step need, `SetupFlow` can be used as well). For example for Google Authenticator (TOTP, Time-based One Time Password) module, the flow will need to be: - -- Generate a secret and store it on instance of setup flow -- Return `async_show_form` with a QR code in the description (injected as base64 via `description_placeholders`) -- User scans code and enters a code to verify it scanned correctly and clock in synced -- TOTP module saved the secret along with user_id, module is enabled for user - -## Workflow - -![Multi Factor Authentication Workflow](/img/en/auth/mfa_workflow.png) - - - -## Configuration example - -```yaml -# configuration.xml -homeassistant: - auth_providers: - - type: homeassistant - - type: legacy_api_password - auth_mfa_modules: - - type: totp - - type: insecure_example - users: [{'user_id': 'a_32_bytes_length_user_id', 'pin': '123456'}] -``` - -In this example, user will first select from `homeassistant` or `legacy_api_password` auth provider. For `homeassistant` auth provider, user will first input username/password, if that user enabled both `totp` and `insecure_example`, then user need select one auth module, then input Google Authenticator code or input pin code base on the selection. - -> insecure_example is only for demo purpose, please do not use it in production. - -## Validation session - -Not like auth provider, auth module use session to manage the validation. After auth provider validated, mfa module will create a validation session, include an experiation time and user_id from auth provider validate result. Mutli-factor auth module will not only verify the user input, but also verify the session is not expired. The validation session data is stored in your configuration directory. \ No newline at end of file diff --git a/website/translated_docs/nl/auth_auth_provider.md b/website/translated_docs/nl/auth_auth_provider.md deleted file mode 100644 index b652973d..00000000 --- a/website/translated_docs/nl/auth_auth_provider.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Authentication Providers" ---- - -Authentication providers confirm the identity of users. The user proofs their identity by going through the login flow for an auth provider. The auth provider defines the login flow and can ask the user all information this needs. This will commonly be username and password but could also include a 2FA token or other challenges. - -Once an authentication provider has confirmed the identity of a user, it will pass that on to Home Assistant in the form of a Credentials object. - -## Defining an auth provider - -> We currently only support built-in auth providers. Support for custom auth providers might arrive in the future. - -Auth providers are defined in `homeassistant/auth/providers/.py`. The auth provider module will need to provide an implementation of the `AuthProvider` class and `LoginFlow` class, it is what asks user for information and validates it base on `data_entry_flow`. - -For an example of a fully implemented auth provider, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/providers/insecure_example.py). - -Auth providers shall extend the following methods of `AuthProvider` class. - -| method | Required | Description | -| ---------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| async def async_login_flow(self) | Yes | Return an instance of the login flow for a user to identify itself. | -| async def async_get_or_create_credentials(self, flow_result) | Yes | Given the result of a login flow, return a credentials object. This can either be an existing one or a new one. | -| async def async_user_meta_for_credentials(credentials) | No | Callback called Home Assistant is going to create a user from a Credentials object. Can be used to populate extra fields for the user. | - -Auth providers shall extend the following methods of `LoginFlow` class. - -| method | Required | Description | -| -------------------------------------------------- | -------- | ------------------------------------------------ | -| async def async_step_init(self, user_input=None) | Yes | Handle the login form, see more detail in below. | - -## async_step_init of LoginFlow - -> We may change this inteface in near future. - -`LoginFlow` extends `data_entry_flow.FlowHandler`. The first step of data entry flow is hard coded as `init`, so each flow has to implement `async_step_init` method. The pattern of `async_step_init` likes following pseudo-code: - -```python -async def async_step_init(self, user_input=None): - return self.async_show_form(step_id='init', data_schema='some schema to construct ui form') if user_input is None - return self.async_show_form(step_id='init', errors) if user_input is invalid - return await self.async_finish(username) if user_input is valid -``` \ No newline at end of file diff --git a/website/translated_docs/nl/auth_index.md b/website/translated_docs/nl/auth_index.md deleted file mode 100644 index 695e6c7d..00000000 --- a/website/translated_docs/nl/auth_index.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Authentication" -sidebar_label: Introduction ---- - -Home Assistant has a built-in authentication system allowing different users to interact with Home Assistant. The authentication system consist of various parts. - -![Overview of how the different parts interact](/img/en/auth/architecture.png) - -## Authentication providers - -An authentication provider is used for users to authenticate themselves. It's up to the authentication provider to choose the method of authentication and the backend to use. By default we enable the built-in Home Assistant authentication provider which stores the users securely inside your configuration directory. - -The authentication providers that Home Assistant will use are specified inside `configuration.yaml`. It is possible to have multiple instances of the same authentication provider active. In that case, each will be identified by a unique identifier. Authentication providers of the same type will not share credentials. - -## Credentials - -Credentials store the authentication of a user with a specific authentication provider. It is produced when a user successfully authenticates. It will allow the system to find the user in our system. If the user does not exist, a new user will be created. This user will not be activated but will require approval by the owner. - -It is possible for a user to have multiple credentials linked to it. However, it can only have a single credential per specific authentication provider. - -## Users - -Each person is a user in the system. To log in as a specific user, authenticate with any of the authentication providers that are linked to this user. When a user logs in, it will get a refresh and an access token to make requests to Home Assistant. - -### Owner - -The user that is created during onboarding will be marked as "owner". The owner is able to manage other users and will always have access to all permissions. - -## Groups - -Users are a member of one or more groups. Group membership is how a user is granted permissions. - -## Permission Policy - -This is the permission policy that describes to which resources a group has access. For more information about permissions and policies, see [Permissions](auth_permissions.md). - -## Access and refresh tokens - -Applications that want to access Home Assistant will ask the user to start an authorization flow. The flow results in an authorization code when a user successfully authorizes the application with Home Assistant. This code can be used to retrieve an access and a refresh token. The access token will have a limited lifetime while refresh tokens will remain valid until a user deletes it. - -The access token is used to access the Home Assistant APIs. The refresh token is used to retrieve a new valid access token. - -### Refresh token types - -There are three different types of refresh tokens: - -- *Normal*: These are the tokens that are generated when a user authorizes an application. The application will hold on to these tokens on behalf of the user. -- *Long-lived Access Token*: These are refresh tokens that back a long lived access token. They are created internally and never exposed to the user. -- *System*: These tokens are limited to be generated and used by system users like Hass.io. They are never exposed to the user. \ No newline at end of file diff --git a/website/translated_docs/nl/auth_permissions.md b/website/translated_docs/nl/auth_permissions.md deleted file mode 100644 index 9aed470e..00000000 --- a/website/translated_docs/nl/auth_permissions.md +++ /dev/null @@ -1,266 +0,0 @@ ---- -title: "Permissions" ---- - -> This is an experimental feature that is not enabled or enforced yet - -Permissions limit the things a user has access to or can control. Permissions are attached to groups, of which a user can be a member. The combined permissions of all groups a user is a member of decides what a user can and cannot see or control. - -Permissions do not apply to the user that is flagged as "owner". This user will always have access to everything. - -## General permission structure - -Policies are dictionaries that at the root level consist of different categories of permissions. In the current implementation this is limited to just entities. - -```python -{ - "entities": … -} -``` - -Each category can further split into subcategories that describe parts of that category. - -```python -{ - "entities": { - "domains": …, - "entity_ids": … - } -} -``` - -If a category is omitted, the user will not have permission to that category. - -When defining a policy, any dictionary value at any place can be replaced with `True` or `None`. `True` means that permission is granted and `None` means use default, which is deny access. - -## Entities - -Entity permissions can be set on a per entity and per domain basis using the subcategories `entity_ids`, `device_ids`, `area_ids` and `domains`. You can either grant all access by setting the value to `True`, or you can specify each entity individually using the "read", "control", "edit" permissions. - -The system will return the first matching result, based on the order: `entity_ids`, `device_ids`, `area_ids`, `domains`, `all`. - -```json -{ - "entities": { - "domains": { - "switch": true - }, - "entity_ids": { - "light.kitchen": { - "read": true, - "control": true - } - } - } -} -``` - -## Merging policies - -If a user is a member of multiple groups, the groups permission policies will be combined into a single policy at runtime. When merging policies, we will look at each level of the dictionary and compare the values for each source using the following methodology: - -1. If any of the values is `True`, the merged value becomes `True`. -2. If any value is a dictionary, the merged value becomes a dictionary created by recursively checking each value using this methodology. -3. If all values are `None`, the merged value becomes `None`. - -Let's look at an example: - -```python -{ - "entities": { - "entity_ids": { - "light.kitchen": True - } - } -} -``` - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -Once merged becomes - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -## Checking permissions - -We currently have two different permission checks: can the user do the read/control/edit operation on an entity, and is the user an admin and thus allowed to change this configuration setting. - -Certain APIs will always be accessible to all users, but might offer a limited scope based on the permissions, like rendering a template. - -### Checking permissions - -To check a permission, you will need to have access to the user object. Once you have the user object, checking the permission is easy. - -```python -from homeassistant.exceptions import Unauthorized -from homeasistant.permissions.const import ( - POLICY_READ, POLICY_CONTROL, POLICY_EDIT -) - -# Raise error if user is not an admin -if not user.is_admin: - raise Unauthorized() - - -# Raise error if user does not have access to control an entity -# Available policies: POLICY_READ, POLICY_CONTROL, POLICY_EDIT -if not user.permissions.check_entity(entity_id, POLICY_CONTROL): - raise Unauthorized() -``` - -### The context object - -All service calls, fired events and states in Home Assistant have a context object. This object allows us to attribute changes to events and services. These context objects also contain a user id, which is used for checking the permissions. - -It's crucial for permission checking that actions taken on behalf of the user are done with a context containing the user ID. If you are in a service handler, you should re-use the incoming context `call.context`. If you are inside a WebSocket API or Rest API endpoint, you should create a context with the correct user: - -```python -from homeassistant.core import Context - -await hass.services.async_call('homeassistant', 'stop', context=Context( - user_id=user.id -), blocking=True) -``` - -### If a permission check fails - -When you detect an anauthorized action, you should raise the `homeassistant.exceptions.Unauthorized` exception. This exception will cancel the current action and notifies the user that their action is unauthorized. - -The `Unauthorized` exception has various parameters, to identify the permission check that failed. All fields are optional. - -| # Not all actions have an ID (like adding config entry) | # We then use this fallback to know what category was unauth - -| Parameter | Description | -| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| context | The context of the current call. | -| user_id | The user ID that we tried to operate on. | -| entity_id | The entity ID that we tried to operate on. | -| config_entry_id | The config entry ID that we tried to operate on. | -| perm_category | The permission category that we tested. Only necessary if we don't have an object ID that the user tried to operate on (like when we create a config entry). | -| permission | The permission that we tested, ie `POLICY_READ`. | - -### Securing a service call handler - -Service calls allow a user to control entities or with the integration as a whole. A service call uses the attached context to see which user invoked the command. Because context is used, it is important that you also pass the call context to all service calls. - -All services that are registered via the entity component (`component.async_register_entity_service()`) will automatically have their permissions checked. - -#### Checking entity permissions - -Your service call handler will need to check the permissions for each entity that it will act on. - -```python -from homeassistant.exceptions import Unauthorized, UnknownUser -from homeassistant.auth.permissions.const import POLICY_CONTROL - -async def handle_entity_service(call): - """Handle a service call.""" - entity_ids = call.data['entity_id'] - - for entity_id in entity_ids: - if call.context.user_id: - user = await hass.auth.async_get_user(call.context.user_id) - - if user is None: - raise UnknownUser( - context=call.context, - entity_id=entity_id, - permission=POLICY_CONTROL, - ) - - if not user.permissions.check_entity(entity_id, POLICY_CONTROL): - raise Unauthorized( - context=call.context, - entity_id=entity_id, - permission=POLICY_CONTROL, - ) - - # Do action on entity - - -async def async_setup(hass, config): - hass.services.async_register(DOMAIN, 'my_service', handle_entity_service) - return True -``` - -#### Checking admin permission - -Starting Home Assistant 0.90, there is a special decorator to help protect services that require admin access. - -```python -# New in Home Assistant 0.90 -async def handle_admin_service(call): - """Handle a service call.""" - # Do admin action - - -async def async_setup(hass, config): - hass.helpers.service.async_register_admin_service( - DOMAIN, 'my_service', handle_admin_service, vol.Schema({}) - ) - return True -``` - -### Securing a REST API endpoint - -```python -from homeassistant.core import Context -from homeassistant.components.http.view import HomeAssistantView -from homeassistant.exceptions import Unauthorized - - -class MyView(HomeAssistantView): - """View to handle Status requests.""" - - url = '/api/my-component/my-api' - name = 'api:my-component:my-api' - - async def post(self, request): - """Notify that the API is running.""" - hass = request.app['hass'] - user = request['hass_user'] - - if not user.is_admin: - raise Unauthorized() - - hass.bus.async_fire('my-component-api-running', context=Context( - user_id=user.id - )) - - return self.json_message("Done.") -``` - -### Securing a Websocket API endpoint - -Verifying permissions in a Websocket API endpoint can be done by accessing the user via `connection.user`. If you need to check admin access, you can use the built-in `@require_admin` decorator. - -```python -from homeassistant.compnents import websocket_api - - -async def async_setup(hass, config): - hass.components.websocket_api.async_register_command(websocket_create) - return True - - -@websocket_api.require_admin -@websocket_api.async_response -@websocket_api.websocket_command({ - vol.Required('type'): 'my-component/my-action', -}) -async def websocket_create(hass, connection, msg): - """Create a user.""" - # Do action -``` \ No newline at end of file diff --git a/website/translated_docs/nl/config_entries_config_flow_handler.md b/website/translated_docs/nl/config_entries_config_flow_handler.md deleted file mode 100644 index 6fe750d0..00000000 --- a/website/translated_docs/nl/config_entries_config_flow_handler.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Integration Configuration -sidebar_label: Configuration ---- - -> This option is currently only available for built-in components. - -Integrations can be set up via the user interface by adding support for config entries. Config entries uses the [data flow entry framework](data_entry_flow_index.md) to allow users to create entries. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like Hass.io). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -To register your config flow handler with Home Assistant, register it with the config entries `HANDLERS` registry: - -```python -from homeassistant import config_entries - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(config_entries.ConfigFlow): -``` - -All config flow handlers will also need to add their domain name to the `FLOWS` constant in `homeassistant/config_entries.py`. - -## Discovering your config flow - -Home Assistant has a discovery integration that scans the network for available devices and services and will trigger the config flow of the appropriate integration. Discovery is limited to UPnP and zeroconf/mDNS. - -To have your integration be discovered, you will have to extend the [NetDisco library](https://github.com/home-assistant/netdisco) to be able to find your device. This is done by adding a new discoverable. [See the repository for examples of existing discoverable.](https://github.com/home-assistant/netdisco/tree/master/netdisco/discoverables) - -Once done, you will have to update the discovery integration to make it aware which discovery maps to which integration, by updating [this list](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery/__init__.py#L55). - -Finally, you will have to add support to your config flow to be triggered from discovery. This is done by adding a new discovery step. Make sure that your discovery step does not automatically create an entry. All discovered config flows are required to have a confirmation from the user. - -Once discovered, the user will be notified that they can continue the flow from the config panel. - -```python -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` - -When the translations are merged into Home Assistant, they will be automatically uploaded to [Lokalise](https://lokalise.co/) where the translation team will help to translate them in other languages. [More info on translating Home Assistant.](internationalization_translation.md) - -## Triggering other config flows - -If you are writing an integration that discovers other integrations, you will want to trigger their config flows so the user can set them up. Do this by passing a source parameter and optional user input when initializing the config entry: - -```python -await hass.config_entries.flow.async_init( - 'hue', data=discovery_info, - context={'source': config_entries.SOURCE_DISCOVERY}) -``` \ No newline at end of file diff --git a/website/translated_docs/nl/config_entries_index.md b/website/translated_docs/nl/config_entries_index.md deleted file mode 100644 index 2416509c..00000000 --- a/website/translated_docs/nl/config_entries_index.md +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: Config Entries -sidebar_label: Introduction ---- - -Config Entries are configuration data that are persistently stored by Home Assistant. A config entry is created by a user via the UI. The UI flow is powered by a [config flow handler](config_entries_config_flow_handler.md) as defined by the component. Config entries can also have an extra [options flow handler](config_entries_options_flow_handler.md), also defined by the component. - -## Lifecycle - -| State | Description | -| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| not loaded | The config entry has not been loaded. This is the initial state when a config entry is created or when Home Assistant is restarted. | -| loaded | The config entry has been loaded. | -| setup error | An error occurred when trying to set up the config entry. | -| setup retry | A dependency of the config entry was not ready yet. Home Assistant will automatically retry loading this config entry in the future. Time between attempts will automatically increase. | -| migration error | The config entry had to be migrated to a newer version, but the migration failed. | -| failed unload | The config entry was attempted to be unloaded, but this was either not supported or it raised an exception. | -G - - - - - not loaded - - -not loaded - - - loaded - - -loaded - - - not loaded->loaded - - - - - - - setup error - - -setup error - - - not loaded->setup error - - - - - - - setup retry - - -setup retry - - - not loaded->setup retry - - - - - - - migration error - - -migration error - - - not loaded->migration error - - - - - - - loaded->not loaded - - - - - - - failed unload - - -failed unload - - - loaded->failed unload - - - - - - - setup error->not loaded - - - - - - - setup retry->not loaded - - - - - - - -## Setting up an entry - -During startup, Home Assistant first calls the [normal component setup](https://developers.home-assistant.io/docs/en/creating_component_index.html), and then call the method `async_setup_entry(hass, entry)` for each entry. If a new Config Entry is created at runtime, Home Assistant will also call `async_setup_entry(hass, entry)` ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L119)). - -#### For platforms - -If a component includes platforms, it will need to forward the Config Entry to the platform. This can be done by calling the forward function on the config entry manager ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/bridge.py#L81)): - -```python -# Use `hass.async_add_job` to avoid a circular dependency between the platform and the component -hass.async_add_job(hass.config_entries.async_forward_entry_setup(config_entry, 'light')) -``` - -For a platform to support config entries, it will need to add a setup entry method ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/light/hue.py#L60)): - -```python -async def async_setup_entry(hass, config_entry, async_add_devices): -``` - -## Unloading entries - -Components can optionally support unloading a config entry. When unloading an entry, the component needs to clean up all entities, unsubscribe any event listener and close all connections. To implement this, add `async_unload_entry(hass, entry)` to your component ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L136)). - -For each platform that you forwarded the config entry to, you will need to forward the unloading too. - -```python -await self.hass.config_entries.async_forward_entry_unload(self.config_entry, 'light') -``` - -If you need to clean up resources used by an entity in a platform, have the entity implement the [`async_will_remove_from_hass`](entity_index.md#async_will_remove_from_hass) method. - -## Removal of entries - -If a component needs to clean up code when an entry is removed, it can define a removal method: - -```python -async def async_remove_entry(hass, entry) -> None: - """Handle removal of an entry.""" -``` \ No newline at end of file diff --git a/website/translated_docs/nl/config_entries_options_flow_handler.md b/website/translated_docs/nl/config_entries_options_flow_handler.md deleted file mode 100644 index 03be7419..00000000 --- a/website/translated_docs/nl/config_entries_options_flow_handler.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Integration Configuration Options -sidebar_label: Configuration Options ---- - -> This option is currently only available for built-in components. - -An integration that is configured via a config entry can expose options to the user to allow tweaking behavior of the integration, like which devices or locations should be integrated. - -Config Entry Options uses the [Data Flow Entry framework](data_entry_flow_index.md) to allow users to update a config entries options. Components that want to support config entry options will need to define a Options Flow Handler. - -## Options support - -For an integration to support options it needs to have an `async_get_options_flow` method in its config flow handler. Calling it will return an instance of the components options flow handler. - -```python -@staticmethod -@callback -def async_get_options_flow(config, options): - return OptionsFlowHandler(config, options) -``` - -## Flow handler - -The Flow handler works just like the config flow handler, except that the first step in the flow will always be `async_step_init`. - -```python -class OptionsFlowHandler(data_entry_flow.FlowHandler): - def __init__(self, config, options): -``` - -## Signal updates - -If the component should act on updated options, you can register an update listener to the config entry that will be called when the entry is updated. - -```python -entry.add_update_listener(update_listener) -``` - -The Listener shall be an async function that takes the same input as async_setup_entry. Options can then be accessed from `entry.options`. - -```python -async def update_listener(hass, entry): -``` \ No newline at end of file diff --git a/website/translated_docs/nl/configuration_yaml_index.md b/website/translated_docs/nl/configuration_yaml_index.md deleted file mode 100644 index 15f42083..00000000 --- a/website/translated_docs/nl/configuration_yaml_index.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: "Integration Configuration via YAML" -sidebar_label: Configuration via YAML ---- - -`configuration.yaml` is a configuration file defined by the user. It is automatically created by Home Assistant on first launch. It defines which components to load. - -## Pre-processing - -Home Assistant will do some pre-processing on the config based on the components that are specified to load. - -### CONFIG_SCHEMA - -If a component defines a variable `CONFIG_SCHEMA`, the config object that is passed in will be the result of running the config through `CONFIG_SCHEMA`. `CONFIG_SCHEMA` should be a voluptuous schema. - -### PLATFORM_SCHEMA - -If a component defines a variable `PLATFORM_SCHEMA`, the component will be treated as an entity component. The configuration of entity components is a list of platform configurations. - -Home Assistant will gather all platform configurations for this component. It will do so by looking for configuration entries under the domain of the component (ie `light`) but also under any entry of domain + extra text. - -While gathering the platform configs, Home Assistant will validate them. It will see if the platform exists and if the platform defines a PLATFORM_SCHEMA, validate against that schema. If not defined, it will validate the config against the PLATFORM_SCHEMA defined in the component. Any configuration that references non existing platforms or contains invalid config will be removed. - -The following `configuration.yaml`: - -```yaml -unrelated_component: - some_key: some_value - -switch: - platform: example1 - -switch living room: - - - platform: example2 - some_config: true - - platform: invalid_platform -``` - -will be passed to the component as - -```python -{ - "unrelated_component": { - "some_key": "some_value" - }, - "switch": [ - { - "platform": "example1" - }, - { - "platform": "example2, - "some_config": True - } - ] -} -``` \ No newline at end of file diff --git a/website/translated_docs/nl/creating_component_code_review.md b/website/translated_docs/nl/creating_component_code_review.md deleted file mode 100644 index 2a87cc44..00000000 --- a/website/translated_docs/nl/creating_component_code_review.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: "Checklist for creating a component" -sidebar_label: Component Checklist ---- - -A checklist of things to do when you're adding a new component. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - -1. Follow our [Style guidelines](development_guidelines.md) -2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - - Only add new constants to `const.py` if they are widely used. Otherwise keep them on components level - -### 1. Requirements - -1. Requirements have been added to [`manifest.json`](creating_integration_manifest.md). The `REQUIREMENTS` constant is deprecated. -2. Requirement version should be pinned: `"requirements": ['phue==0.8.1']` -3. We no longer want requirements hosted on GitHub. Please upload to PyPi. -4. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Configuration - -1. Voluptuous schema present for [configuration validation](development_validation.md) -2. Default parameters specified in voluptuous schema, not in `setup(…)` -3. Schema using as many generic config keys as possible from `homeassistant.const` -4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`. -5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation` -6. Never depend on users adding things to `customize` to configure behavior inside your component. - -### 3. Component/platform communication - -1. You can share data with your platforms by leveraging `hass.data[DOMAIN]`. -2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`. - -### 4. Communication with devices/services - -1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - - ```python - # bad - status = requests.get(url('/status')) - - # good - from phue import Bridge - bridge = Bridge(...) - status = bridge.status() - ``` - - [Tutorial on publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) - -### 5. Make your pull request as small as possible - -Keep a new integration to the minimum functionality needed for someone to get value out of the integration. This allows reviewers to sign off on smaller chunks of code one at a time, and lets us get your new integration/features in sooner. **Pull requests containing large code dumps will not be a priority for review and may be closed.** - -- Limit to a single platform -- Do not add features not needed to directly support the single platform (such as custom services) -- Do not mix clean-ups and new features in a single pull request. -- Do not solve several issues in a single pull request. -- Do not submit pull requests that depend on other work which is still unmerged. - -### 6. Event names - -Prefix component event names with the domain name. For example, use `netatmo_person` instead of `person` for the `netatmo` component. - -### 7. Tests - -Strongly consider adding tests for your component to minimize future regressions. \ No newline at end of file diff --git a/website/translated_docs/nl/creating_component_deps_and_reqs.md b/website/translated_docs/nl/creating_component_deps_and_reqs.md deleted file mode 100644 index c7826476..00000000 --- a/website/translated_docs/nl/creating_component_deps_and_reqs.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: "" ---- - -[This page has moved.](creating_integration_manifest.md) - - diff --git a/website/translated_docs/nl/creating_component_generic_discovery.md b/website/translated_docs/nl/creating_component_generic_discovery.md deleted file mode 100644 index cf5fc3a1..00000000 --- a/website/translated_docs/nl/creating_component_generic_discovery.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: "Integration with Multiple Platforms" -sidebar_label: Multiple platforms ---- - -Most integrations consist of a single platform. And in that case, it's fine to just define that one platform. However, if you are going to add a second platform, you will want to centralize your connection logic. This is done inside the component (`__init__.py`). - -If your integration is configurable via `configuration.yaml`, it will cause the entry point of your configuration to change, as now users will need to set up your integration directly, and it is up to your integration to set up the platforms. - -## Loading platforms when configured via a config entry - -If your integration is set up via a config entry, you will need to forward the config entry to the appropriate integration to set up your platform. For more info, see the [config entry documentation](config_entries_index.md#for-platforms). - -## Loading platforms when configured via configuration.yaml - -If your integration is not using config entries, it will have to use our discovery helpers to set up its platforms. Note, this approach does not support unloading. - -To do this, you will need to use the `load_platform` and `async_load_platform` methods from the discovery helper. - -- See also a [full example that implementing this logic](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_load_platform/) \ No newline at end of file diff --git a/website/translated_docs/nl/creating_component_index.md b/website/translated_docs/nl/creating_component_index.md deleted file mode 100644 index 9f02858f..00000000 --- a/website/translated_docs/nl/creating_component_index.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "Creating a Minimal Component" -sidebar_label: "Minimal Component" ---- - -Alright, you learned about the [manifest](creating_integration_manifest.md), so it's time to write your first code for your integration. AWESOME. Don't worry, we've tried hard to keep it as easy as possible. - -More extensive examples of integrations are available from [our example repository](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/). - -## The code - -Each component needs to have 2 basic parts: it needs to define a `DOMAIN` constant that contains the domain of the integration. The second part is that it needs to define a setup method that returns a boolean if the set up was successful. So let's take a look at how this looks: - -```python -DOMAIN = 'hello_state' - -def setup(hass, config): - hass.states.set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -And if you prefer an async component: - -```python -DOMAIN = 'hello_state' - -async def async_setup(hass, config): - hass.states.async_set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -That's it! If you load this, you will see a new state in the state machine. - -To load this, add `hello_state:` to your `configuration.yaml` file and create a file `/custom_components/hello_state/__init__.py` with one of the two codeblocks above to test it locally. \ No newline at end of file diff --git a/website/translated_docs/nl/creating_integration_file_structure.md b/website/translated_docs/nl/creating_integration_file_structure.md deleted file mode 100644 index 3a535d07..00000000 --- a/website/translated_docs/nl/creating_integration_file_structure.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Integration File Structure" -sidebar_label: "File Structure" ---- - -Each integration is stored inside a directory named after the integration domain. The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. So all files for this integration are in the folder `mobile_app/`. - -The bare minimum content of this folder looks like this: - -- `manifest.json`: The manifest file describes the integration and its dependencies. [More info](creating_integration_manifest.md) -- `__init__.py`: The component file. If the integration only offers a platform, you can keep this file limited to a docstring introducing the integration `"""The Mobile App integration."""`. - -## Integrating devices - `light.py`, `switch.py` etc - -If your integration is going to integrate one or more devices, you will need to do this by creating a platform that interacts with an entity integration. For example, if you want to represent a light device inside Home Assistant, you will create `light.py`, which will contain a light platform for the light integration. - -- More info on [available entity integrations](entity_index.md). -- More info on [creating platforms](creating_platform_index.md). - -## Integrating services - `services.yaml` - -If your integration is going to register services, it will need to provide a description of the available services. The description is stored in `services.yaml`. [More information about `services.yaml`.](dev_101_services.md) - -## Where Home Assistant looks for integrations - -Home Assistant will look for an integration when it sees the domain referenced in the config file (i.e. `mobile_app:`) or if it is a dependency of another integration. Home Assistant will look at the following locations: - -- `/custom_components/` -- `homeassistant/components/` (built-in integrations) - -You can override a built-in integration by having an integration with the same domain in your `config/custom_components` folder. Note that overriding built-in components is not recommended as you will no longer get updates. It is recommended to pick a unique name. \ No newline at end of file diff --git a/website/translated_docs/nl/creating_integration_manifest.md b/website/translated_docs/nl/creating_integration_manifest.md deleted file mode 100644 index 7c76a6d7..00000000 --- a/website/translated_docs/nl/creating_integration_manifest.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "Integration Manifest" -sidebar_label: "Manifest" ---- - -Since 0.92.0, every integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, except for custom components. - -```json -{ - "domain": "hue", - "name": "Philips Hue", - "documentation": "https://www.home-assistant.io/components/hue", - "dependencies": ["mqtt"], - "codeowners": ["@balloob"], - "requirements": ["aiohue==1.9.1"] -} -``` - -Or a minimal example that you can copy into your project: - -```json -{ - "domain": "your_domain_name", - "name": "Your Integration", - "documentation": "https://www.example.com", - "dependencies": [], - "codeowners": [], - "requirements": [] -} -``` - -## Domain - -The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. - -## Name - -The name of the integration. - -## Documentation - -The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/` - -## Dependencies - -Dependencies are other Home Assistant integrations that you want Home Assistant to set up successfully prior to the integration being loaded. This can be necessary in case you want to offer functionality from that other integration, like using webhooks or an MQTT connection. - -## Code Owners - -GitHub usernames or team names of people that are responsible for this integration. You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included. - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you running in a virtual environment. This will make sure that all requirements are present at startup. If steps fail, like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is an array of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v3.2.0: `["pychromecast==3.2.0"]`. - -> Because of how Home Assistant installs requirements on demand, actual Python imports of your requirements should be done inside functions instead of at the root level of your Python files. - -### Custom requirements during development & testing - -During the development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using `pychromecast` as an example: - -```bash -pip install pychromecast==3.2.0 --target ~/.homeassistant/deps -hass --skip-pip -``` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is specified in `requirements`. - -If you need to make changes to a requirement to support your component, it's also possible to install a development version of the requirement using `pip install -e`: - -```bash -git clone https://github.com/balloob/pychromecast.git -pip install -e ./pychromecast -hass --skip-pip -``` \ No newline at end of file diff --git a/website/translated_docs/nl/creating_platform_code_review.md b/website/translated_docs/nl/creating_platform_code_review.md deleted file mode 100644 index a7609f74..00000000 --- a/website/translated_docs/nl/creating_platform_code_review.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: "Checklist for creating a platform" -sidebar_label: Platform Checklist ---- - -A checklist of things to do when you're adding a new platform. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - -1. Follow our [Style guidelines](development_guidelines.md) -2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - - Only add new constants to `const.py` if they are widely used. Otherwise keep them on platform level - - Use `CONF_MONITORED_CONDITIONS` instead of `CONF_MONITORED_VARIABLES` - -### 1. Requirements - -1. Requirements have been added to [`manifest.json`](creating_integration_manifest.md). The `REQUIREMENTS` constant is deprecated. -2. Requirement version should be pinned: `"requirements": ['phue==0.8.1']` -3. We no longer want requirements hosted on GitHub. Please upload to PyPi. -4. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Dependencies - -1. If you depend on a component for the connection, add it to your dependencies in [`manifest.json`](creating_integration_manifest.md): `"dependencies": ['nest']`. The `DEPENDENCIES` constant is deprecated. - -### 3. Configuration - -1. Voluptuous schema present for [configuration validation](development_validation.md) -2. Voluptuous schema extends schema from component - (e.g., `hue.light.PLATFORM_SCHEMA` extends `light.PLATFORM_SCHEMA`) -3. Default parameters specified in voluptuous schema, not in `setup_platform(...)` -4. Your `PLATFORM_SCHEMA` should use as many generic config keys as possible from `homeassistant.const` -5. Never depend on users adding things to `customize` to configure behavior inside your platform. - -```python -import voluptuous as vol - -from homeassistant.const import CONF_FILENAME, CONF_HOST -from homeassistant.components.light import PLATFORM_SCHEMA -import homeassistant.helpers.config_validation as cv - -CONF_ALLOW_UNREACHABLE = 'allow_unreachable' -DEFAULT_UNREACHABLE = False - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_ALLOW_UNREACHABLE, - default=DEFAULT_UNREACHABLE): cv.boolean, - vol.Optional(CONF_FILENAME): cv.string, -}) -``` - -### 4. Setup Platform - -1. Verify that the passed in configuration (user/pass/host etc.) works. -2. Group your calls to `add_devices` if possible. -3. If the platform adds extra services, the format should be `.`. So if your integration's domain is "awesome_sauce" and you are making a light platform, you would register services under the `awesome_sauce` domain. Make sure that your services [verify permissions](auth_permissions.md#checking-permissions). - -### 5. Entity - -1. Extend the entity from the integration you're building a platform for. - - ```python - from homeassistant.components.light import Light - - class HueLight(Light): - ... - ``` - -2. Avoid passing in `hass` as a parameter to the entity. When the entity has been added to Home Assistant, `hass` will be set on the entity when the entity is added to Home Assistant. This means you can access `hass` as `self.hass` inside the entity. - -3. Do not call `update()` in constructor, use `add_entities(devices, True)` instead. -4. Do not do any I/O inside properties. Cache values inside `update()` instead. -5. When dealing with time, state and/or attributes should not contain relative time since something happened. Instead, it should store UTC timestamps. -6. Leverage the [entity lifecycle callbacks](entity_index.md#lifecycle-hooks) to attach event listeners or clean up connections. - -### 6. Communication with devices/services - -1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - - ```python - # bad - status = requests.get(url('/status')) - - # good - from phue import Bridge - bridge = Bridge(...) - status = bridge.status() - ``` - - [Tutorial on publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) \ No newline at end of file diff --git a/website/translated_docs/nl/creating_platform_example_light.md b/website/translated_docs/nl/creating_platform_example_light.md deleted file mode 100644 index 2eb9bdbd..00000000 --- a/website/translated_docs/nl/creating_platform_example_light.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: "" ---- - -[This page has moved.](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_light) - - diff --git a/website/translated_docs/nl/creating_platform_example_sensor.md b/website/translated_docs/nl/creating_platform_example_sensor.md deleted file mode 100644 index 97d1683d..00000000 --- a/website/translated_docs/nl/creating_platform_example_sensor.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: "" ---- - -[This page has moved.](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_sensor) - - diff --git a/website/translated_docs/nl/creating_platform_index.md b/website/translated_docs/nl/creating_platform_index.md deleted file mode 100644 index 4a8cab3f..00000000 --- a/website/translated_docs/nl/creating_platform_index.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Integration Platforms" -sidebar_label: "Platforms" ---- - -Home Assistant has various built-in integrations that abstract device types. There are [lights](entity_light.md), [switches](entity_switch.md), [covers](entity_cover.md), [climate devices](entity_climate.md), and [many more](entity_index.md). Your integration can hook into these integrations by creating a platform. You will need a platform for each integration that you are integrating with. - -To create a platform, you will need to create a file with the domain name of the integration that you are building a platform for. So if you are building a light, you will add a new file `light.py` to your integration folder. - -We have created two example integrations that should give you a look at how this works: - -- [Example sensor platform](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_sensor/): hello world of platforms. -- [Example light platform](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_light/): showing best practices. - -### Interfacing with devices - -One Home Assistant rule is that the integration should never interface directly with devices. Instead, it should interact with a third-party Python 3 library. This way, Home Assistant can share code with the Python community and keep the project maintainable. - -Once you have your Python library ready and published to PyPI, add it to the [manifest](creating_integration_manifest.md). It will now be time to implement the Entity base class that is provided by the integration that you are creating a platform for. - -Find your integration at the [entity index](entity_index.md) to see what methods and properties are available to implement. \ No newline at end of file diff --git a/website/translated_docs/nl/data_entry_flow_index.md b/website/translated_docs/nl/data_entry_flow_index.md deleted file mode 100644 index bd2e3b20..00000000 --- a/website/translated_docs/nl/data_entry_flow_index.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -title: Data Entry Flow -sidebar_label: Introduction ---- - -Data Entry Flow is a data entry framework that is part of Home Assistant. Data entry is done via data entry flows. A flow can represent a simple login form or a multi-step setup wizard for a component. A Flow Manager is managing all flows that are in progress and handles creation of new flows. - -Data Entry Flow is being used in Home Assistant to create config entries. - -## Flow Manager - -This is the class that manages the flows that are in progress. When instantiating one, you pass in two async callbacks: - -```python -async def async_create_flow(handler, context=context, data=data) -``` - -The manager delegates instantiating of config flow handlers to this async callback. This allows the parent of the manager to define their own way of finding handlers and preparing a handler for instantiation. For example, in the case of the config entry manager, it will make sure that the dependencies and requirements are setup. - -```python -async def async_finish_flow(flow, result) -``` - -This async callback is called when a flow is finished or aborted. i.e. `result['type'] in [RESULT_TYPE_CREATE_ENTRY, RESULT_TYPE_ABORT]`. The callback function can modify result and return it back, if the result type changed to `RESULT_TYPE_FORM`, the flow will continue running, display another form. - -If the result type is `RESULT_TYPE_FORM`, the result should like: - -```python -{ - # The result type of the flow - 'type': RESULT_TYPE_FORM, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # name of the step, flow.async_step_[step_id] will be called when form submitted - 'step_id': 'init', - # a voluptuous schema to build and validate user input - 'data_schema': vol.Schema(), - # an errors dict, None if no errors - 'errors': errors, - # a detail information about the step - 'description_placeholders': description_placeholders, -} -``` - -If the result type is `RESULT_TYPE_CREATE_ENTRY`, the result should like: - -```python -{ - # Data schema version of the entry - 'version': 2, - # The result type of the flow - 'type': RESULT_TYPE_CREATE_ENTRY, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # title and data as created by the handler - 'title': 'Some title', - 'result': { - 'some': 'data' - }, -} -``` - -If the result type is `RESULT_TYPE_ABORT`, the result should like: - -```python -{ - # The result type of the flow - 'type': RESULT_TYPE_ABORT, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # the abort reason - 'reason': 'already_configured', -} -``` - -## Flow Handler - -Flow handlers will handle a single flow. A flow contains one or more steps. When a flow is instantiated, the `FlowHandler.init_step` step will be called. Each step has three different possible results: "Show Form", "Abort" and "Create Entry". - -At a minimum, each flow handler will have to define a version number and a step. This doens't have to be `init`, as `async_create_flow` can assign `init_step` depends on diffreent workflow, for example in configuration, `context.source` will be use as `init_step`. - -The bare minimum config flow: - -```python -from homeassistant import data_entry_flow - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - # The schema version of the entries that it creates - # Home Assistant will call your migrate method if the version changes - # (this is not implemented yet) - VERSION = 1 - - async def async_step_user(self, user_input=None): - # Do something -``` - -### Show Form - -This result type will show a form to the user to fill in. You define the current step, the schema of the data (using voluptuous) and optionally a dictionary of errors. Title and description of the step will be provided via the translation file. Where this is defined depends on the context of the data entry flow. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema) - ) -``` - -After the user has filled in the form, the step method will be called again and the user input is passed in. Your step will only be called if the user input passes your data schema. When the user passes in data, you will have to do extra validation of the data. For example, you can verify that the passed in username and password are valid. - -If something is wrong, you can return a dictionary with errors. Each key in the error dictionary refers to a field name that contains the error. Use the key `base` if you want to show an error unrelated to a specific field. The specified errors need to refer to a key in a translation file. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # See next section on create entry usage - return self.create_entry(...) - - errors['base'] = 'auth_error' - - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema), - errors=errors - ) -``` - -#### Multi-step flows - -If the user input passes validation, you can again return one of the three return values. If you want to navigate the user to the next step, return the return value of that step: - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_init(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # Store info to use in next step - self.init_info = user_input - # Return the form of the next step - return await self.async_step_account() - - ... -``` - -### Create Entry - -When the result is "Create Entry", an entry will be created and passed to the parent of the flow manager. A success message is shown to the user and the flow is finished. You create an entry by passing a title and data. The title can be used in the UI to indicate to the user which entry it is. Data can be any data type, as long as it is JSON serializable. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - return self.create_entry( - title='Title of the entry', - data={ - 'something_special': user_input['username'] - } - ) -``` - -### Abort - -When a flow cannot be finished, you need to abort it. This will finish the flow and inform the user that the flow has finished. Reasons for a flow to not be able to finish can be that a device is already configured or not compatible with Home Assistant. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - return self.async_abort( - reason='not_supported' - ) -``` - -## Translations - -Data entry flows depend on translations for showing the text in the forms. It depends on the parent of a data entry flow manager where this is stored. - -## Initializing a config flow from an external source - -You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing a flow: - -```python -await flow_mgr.async_init('hue', context={'source': data_entry_flow.SOURCE_DISCOVERY}, data=discovery_info) -``` - -The config flow handler will not start with the `init` step. Instead, it will be instantiated with a step name equal to the source. The step should follow the same return values as a normal step. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` \ No newline at end of file diff --git a/website/translated_docs/nl/dev_101_config.md b/website/translated_docs/nl/dev_101_config.md deleted file mode 100644 index e91e5f31..00000000 --- a/website/translated_docs/nl/dev_101_config.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Using Config" ---- - -Based on where you are in the code, `config` can mean various things. - -### On the hass object - -On the hass object is an instance of the Config class. The Config class contains the users preferred units, the path to the config directory and which components are loaded. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config) - -### Config passed into component setup - -The `config` parameter passed to a component setup is a dictionary containing all of the user supplied configuration. The keys of the dictionary are the component names and the value is another dictionary with the component configuration. - -The object will have already been validated using your `CONFIG_SCHEMA` or `PLATFORM_SCHEMA` if available. If you have defined a `PLATFORM_SCHEMA`, all references to your component (ie `light 2:` etc) will have been changed to be accessible as a list under `config[DOMAIN]`. - -If your configuration file contains the following lines: - -```yaml -example: - host: paulusschoutsen.nl -``` - -Then in the setup method of your component you will be able to refer to `config['example']['host']` to get the value `paulusschoutsen.nl`. - -### Passed into platform setup - -The `config` parameter passed to a platform setup function is only the config for that specific platform. \ No newline at end of file diff --git a/website/translated_docs/nl/dev_101_events.md b/website/translated_docs/nl/dev_101_events.md deleted file mode 100644 index f6f38462..00000000 --- a/website/translated_docs/nl/dev_101_events.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "Using Events" ---- - -The core of Home Assistant is driven by events. That means that if you want to respond to something happening, you'll have to respond to events. Most of the times you won't interact directly with the event system but use one of the [event listener helpers](https://dev-docs.home-assistant.io/en/master/api/helpers.html#module-homeassistant.helpers.event). - -The event system is very flexible. There are no limitations on the event type, as long as it's a string. Each event can contain data. The data is a dictionary that can contain any data as long as it's JSON serializable. This means that you can use number, string, dictionary and list. - -[List of events that Home Assistant fires.](https://www.home-assistant.io/docs/configuration/events/) - -## Firing events - -To fire an event, you have to interact with the event bus. The event bus is available on the Home Assistant instance as `hass.bus`. - -Example component that will fire an event when loaded. Note that custom event names are prefixed with the component name. - -```python -DOMAIN = 'example_component' - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - # Fire event example_component_my_cool_event with event data answer=42 - hass.bus.fire('example_component_my_cool_event', { - 'answer': 42 - }) - - # Return successful setup - return True -``` - -## Listening to events - -Most of the times you'll not be firing events but instead listen to events. For example, the state change of an entity is broadcasted as an event. - -```python -DOMAIN = 'example_component' - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - count = 0 - - # Listener to handle fired events - def handle_event(event): - nonlocal count - count += 1 - print('Answer {0} is: {1}'.format(count, event.data.get('answer'))) - - # Listen for when example_component_my_cool_event is fired - hass.bus.listen('example_component_my_cool_event', handle_event) - - # Return successful setup - return True -``` - -### Helpers - -Home Assistant comes with a lot of bundled helpers to listen to specific types of event. There are helpers to track a point in time, to track a time interval, a state change or the sun set. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/helpers.html#module-homeassistant.helpers.event) \ No newline at end of file diff --git a/website/translated_docs/nl/dev_101_hass.md b/website/translated_docs/nl/dev_101_hass.md deleted file mode 100644 index bc8d414e..00000000 --- a/website/translated_docs/nl/dev_101_hass.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "Hass object" ---- - -While developing Home Assistant you will see a variable that is everywhere: `hass`. This is the Home Assistant instance that will give you access to all the various parts of the system. - -### The `hass` object - -The Home Assistant instance contains four objects to help you interact with the system. - -| Object | Description | -| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `hass` | This is the instance of Home Assistant. Allows starting, stopping and enqueing new jobs. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.HomeAssistant) | -| `hass.config` | This is the core configuration of Home Assistant exposing location, temperature preferences and config directory path. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config) | -| `hass.states` | This is the StateMachine. It allows you to set states and track when they are changed. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.StateMachine) | -| `hass.bus` | This is the EventBus. It allows you to trigger and listen for events. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.EventBus) | -| `hass.services` | This is the ServiceRegistry. It allows you to register services. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.ServiceRegistry) | - -### Where to find `hass` - -Depending on what you're writing, there are different ways the `hass` object is made available. - -**Component** -Passed into `setup(hass, config)` or `async_setup(hass, config)`. - -**Platform** -Passed into `setup_platform(hass, config, add_devices, discovery_info=None)` or `async_setup_platform(hass, config, async_add_devices, discovery_info=None)`. - -**Entity** -Available as `self.hass` once the entity has been added via the `add_devices` callback inside a platform. \ No newline at end of file diff --git a/website/translated_docs/nl/dev_101_index.md b/website/translated_docs/nl/dev_101_index.md deleted file mode 100644 index 9cbf54d8..00000000 --- a/website/translated_docs/nl/dev_101_index.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Development 101" -sidebar_label: Introduction ---- - -The goal of development 101 is to get you familiar with the basics of developing for Home Assistant. Before we start, please make sure you familiarize yourself with the [architecture](architecture_index.md). - -To get our code running inside Home Assistant we're going to create a custom component. The first step is to locate your config folder. You can find the path to your config folder by opening the Home Assistant frontend, click on the service developer tool icon. It's the path after the text "Path to configuration.yaml". - -Inside your configuration directory create a new folder called `custom_components`. It might be that one already exists, that's fine too. This is the folder that Home Assistant will look at when looking for custom code. - -> The Home Assistant API has two variants: a synchronous and an asynchronous version (asyncio). This development course will focus on the synchronous version. - -To verify that everything is working correctly, let's create a small Hello World component. To do so, create a file called `hello_world.py` in your custom components folder. Copy paste the following content to it: - -```python -# The domain of your component. Equal to the filename of your component. -DOMAIN = "hello_world" - - -def setup(hass, config): - """Setup the hello_world component.""" - # States are in the format DOMAIN.OBJECT_ID. - hass.states.set('hello_world.Hello_World', 'Works!') - - # Return boolean to indicate that initialization was successfully. - return True -``` - -Last step is to add `hello_world:` entry to your `configuration.yaml` file. - -```yaml -# Hello World component -hello_world: -``` - -After running `hass`, we should see log entries stating that `hello_world` component was loaded. What is more, additional state card shall appear within main panel. - -```log -2018-04-03 21:44:20 INFO (MainThread) [homeassistant.loader] Loaded hello_world from custom_components.hello_world -2018-04-03 21:44:20 INFO (MainThread) [homeassistant.setup] Setting up hello_world -``` - -![State card showing that Hello World component is working as intended.](/img/en/frontend/hello-world-state-card.png) \ No newline at end of file diff --git a/website/translated_docs/nl/dev_101_services.md b/website/translated_docs/nl/dev_101_services.md deleted file mode 100644 index 7bae113c..00000000 --- a/website/translated_docs/nl/dev_101_services.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: "Integration Services" -sidebar_label: "Custom Services" ---- - -Home Assistant provides ready-made services for a lot of things, but it doesn't always cover everything. Instead of trying to change Home Assistant, it is preferred to add it as a service under your own integration first. Once we see a pattern in these services, we can talk about generalizing them. - -This is a simple "hello world" example to show the basics of registering a service. To use this example, create the file `/custom_components/hello_service/__init__.py` and copy the below example code. - -Services can be called from automations and from the service "Developer tools" in the frontend. - -```python -DOMAIN = 'hello_service' - -ATTR_NAME = 'name' -DEFAULT_NAME = 'World' - - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - def handle_hello(call): - """Handle the service call.""" - name = call.data.get(ATTR_NAME, DEFAULT_NAME) - - hass.states.set('hello_service.hello', name) - - hass.services.register(DOMAIN, 'hello', handle_hello) - - # Return boolean to indicate that initialization was successfully. - return True -``` - -Load the integration by adding the following to your `configuration.yaml`. When your component is loaded, a new service should be available to call. - -```yaml -# configuration.yaml entry -hello_service: -``` - -Open the frontend and in the sidebar, click the first icon in the developer tool section. This will open the Call Service developer tool. On the right, find your service and click on it. This will automatically fill in the correct values. - -Pressing "Call Service" will now call your service without any parameters. This will cause your service to create a state with the default name 'World'. If you want to specify the name, you have to specify parameters. Add the following JSON as Service Data and press "Call Service again". - -```json -{ - "name": "Planet" -} -``` - -The service will now overwrite the previous state with "Planet". - -## Service descriptions - -Adding services is only useful if users know about them. In Home Assistant we use a `services.yaml` as part of your integration to describe the services. - -Services are published under the domain name of your integration, so in `services.yaml` we only use the service name as the base key. - -```yaml -# Example services.yaml entry - -set_speed: - # Description of the service - description: Sets fan speed. - # Different fields that your service accepts - fields: - # Key of the field - entity_id: - # Description of the field - description: Name(s) of the entities to set - # Example value that can be passed for this field - example: 'fan.living_room' - speed: - description: Speed setting - example: 'low' -``` \ No newline at end of file diff --git a/website/translated_docs/nl/dev_101_states.md b/website/translated_docs/nl/dev_101_states.md deleted file mode 100644 index d35379c7..00000000 --- a/website/translated_docs/nl/dev_101_states.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -title: "Using States" ---- - -Home Assistant keeps track of the states of entities in a state machine. The state machine has very few requirements: - -- Each state is related to an entity identified by an entity id. This id is made up of a domain and an object id. For example `light.kitchen_ceiling`. You can make up any combination of domain and object id, even overwriting existing states. -- Each state has a primary attribute that describes the state of the entity. In the case of a light this could be for example "on" and "off". You can store anything you want in the state, as long as it's a string (will be converted if it's not). -- You can store more information about an entity by setting attributes. Attributes is a dictionary that can contain any data that you want. The only requirement is that it's JSON serializable, so you're limited to numbers, strings, dictionaries and lists. - -[Description of the state object.](https://www.home-assistant.io/docs/configuration/state_object/) - -## Using states in your component - -This is a simple tutorial/example on how to create and set states. We will do our work in a component called "hello_state". The purpose of this component is to display a given text in the frontend. - -To get started, create the file `/custom_components/hello_state.py` and copy the below example code. - -```python -""" -Support for showing text in the frontend. - -For more details about this component, please refer to the documentation at -https://home-assistant.io/cookbook/python_component_basic_state/ -""" -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = 'hello_state' - -def setup(hass, config): - """Setup the Hello State component. """ - _LOGGER.info("The 'hello state' component is ready!") - - return True -``` - -1. In the file header we decided to add some details: A short description and the link to the documentation. -2. We want to do some logging. This means that we import the Python logging module and create an alias. -3. The component name is equal to the domain name. -4. The `setup` function will take care of the initialization of our component. The component will only write a log message. Keep in mind for later that you have several options for the severity: - -- `_LOGGER.info(msg)` -- `_LOGGER.warning(msg)` -- `_LOGGER.error(msg)` -- `_LOGGER.critical(msg)` -- `_LOGGER.exception(msg)` - -5. We return `True` if everything is ok. - -Add the component to your `configuration.yaml` file. - -```yaml -hello_state: -``` - -After a start or a restart of Home Assistant the component will create an entry in the log. - -```bash -16-03-12 14:16:42 INFO (MainThread) [custom_components.hello_state] The 'hello state' component is ready! -``` - -The next step is the introduction of configuration options. A user can pass configuration options to our component via `configuration.yaml`. To use them we'll use the passed in `config` variable to our `setup` method. - -```python -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = 'hello_state' - -CONF_TEXT = 'text' -DEFAULT_TEXT = 'No text!' - -def setup(hass, config): - """Set up the Hello State component. """ - # Get the text from the configuration. Use DEFAULT_TEXT if no name is provided. - text = config[DOMAIN].get(CONF_TEXT, DEFAULT_TEXT) - - # States are in the format DOMAIN.OBJECT_ID - hass.states.set('hello_state.Hello_State', text) - - return True -``` - -To use the latest feature of our component, update the entry in your `configuration.yaml` file. - -```yaml -hello_state: - text: 'Hello, World!' -``` - -Thanks to `DEFAULT_TEXT` variable the component will launch even if no `text:` field is used in the `configuration.yaml` file. Quite often there are variables which are required. It's important to check if all mandatory configuration variables are provided. If not, the setup should fail. We will use `voluptuous` as a helper to achieve this. The next listing shows the essential parts. - -```python -import voluptuous as vol - -import homeassistant.helpers.config_validation as cv - -CONFIG_SCHEMA = vol.Schema({ - DOMAIN: vol.Schema({ - vol.Required(CONF_TEXT): cv.string, - }) -}, extra=vol.ALLOW_EXTRA) -``` - -Now, when `text:` is missing from the config, Home Assistant will alert the user and not setup your component. - -After a start or a restart of Home Assistant the component will be visible in the frontend if the `configuration.yaml` file is up-to-date. - -

- -

- -In order to expose attributes for a platform, you will need to define a property called `device_state_attributes` on the entity class, which will return a dictionary of attributes: - - @property - def device_state_attributes(self): - """Return device specific state attributes.""" - return self._attributes - - -> Entities also have a similar property `state_attributes`, which normally doesn't need to be defined by new platforms. This property is used by base components to add standard sets of attributes to a state. Example: The light component uses `state_attributes` to add brightness to the state dictionary. If you are designing a new component, you should define `state_attributes` instead. - -To get your component included in the Home Assistant releases, follow the steps described in the [Submit your work](development_submitting.md) section. Basically you only need to move your component in the `homeassistant/component/` directory of your fork and create a Pull Request. \ No newline at end of file diff --git a/website/translated_docs/nl/development_catching_up.md b/website/translated_docs/nl/development_catching_up.md deleted file mode 100644 index 7f14f6d5..00000000 --- a/website/translated_docs/nl/development_catching_up.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Catching up with Reality" ---- - -If it's taking a while to develop your feature, and you want to catch up with what's in the current Home Assistant `dev` branch, you can use `git rebase`. This will pull the latest Home Assistant changes locally, rewind your commits, bring in the latest changes from Home Assistant, and replay all of your commits on top. - -> If you use the workflow below, it is important that you force push the update as described. Git might prompt you to do `git pull` first. Do **NOT** do that! It would mess up your commit history. - -```bash -# Run this from your feature branch -$ git fetch upstream dev # to pull the latest changes into a local dev branch -$ git rebase upstream/dev # to put those changes into your feature branch before your changes -``` - -If rebase detects conflicts, repeat this process until all changes have been resolved: - -1. `git status` shows you the file with the conflict; edit the file and resolve the lines between `<<<< | >>>>` -2. Add the modified file: `git add ` or `git add .` -3. Continue rebase: `git rebase --continue` -4. Repeat until you've resolved all conflicts - -After rebasing your branch, you will have rewritten history relative to your GitHub fork's branch. When you go to push you will see an error that your history has diverged from the original branch. In order to get your GitHub fork up-to-date with your local branch, you will need to force push, using the following command: - -```bash -# Run this from your feature branch -$ git push origin --force -``` - -Other workflows are covered in detail in the [Github documentation](https://help.github.com/articles/fork-a-repo/). Add an additional `remote` after you clone your fork. - -```bash -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -Then, `git pull --rebase upstream dev`. \ No newline at end of file diff --git a/website/translated_docs/nl/development_checklist.md b/website/translated_docs/nl/development_checklist.md deleted file mode 100644 index 0d1652cd..00000000 --- a/website/translated_docs/nl/development_checklist.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "Development Checklist" -sidebar_label: Introduction ---- - - -Before you commit any changes, check your work against these requirements: - -- All communication to external devices or services must be wrapped in an external Python library hosted on [pypi](https://pypi.python.org/pypi). -- New dependencies are added to `requirements_all.txt` (if applicable), using `python3 -m script.gen_requirements_all` -- New codeowners are added to `CODEOWNERS` (if applicable), using `python3 -m script.hassfest` -- The `.coveragerc` file is updated to exclude your platform if there are no tests available or your new code uses a third-party library for communication with the device, service, or sensor -- Documentation is developed for [home-assistant.io](https://home-assistant.io/) - - Visit the [website documentation](https://www.home-assistant.io/developers/documentation/) for more information about contributing to [home-assistant.io](https://github.com/home-assistant/home-assistant.github.io). \ No newline at end of file diff --git a/website/translated_docs/nl/development_environment.md b/website/translated_docs/nl/development_environment.md deleted file mode 100644 index 9e0bc03c..00000000 --- a/website/translated_docs/nl/development_environment.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -title: "Set up Development Environment" ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example CentOS would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Due to Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run - -```bash -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is set up, perform install as for Linux. - -```bash -$ sudo apt-get update -$ sudo apt-get install python3-pip python3-dev python3-venv -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```bash -$ mkdir -p ../config -$ hass -c ../config -``` - -### Developing on OS X - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 autoconf -``` - -Then install ffmpeg: - -```bash -$ brew install ffmpeg -``` - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv venv -$ source venv/bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```bash -$ hass -``` - -## Logging - -By default logging in Home Assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` \ No newline at end of file diff --git a/website/translated_docs/nl/development_guidelines.md b/website/translated_docs/nl/development_guidelines.md deleted file mode 100644 index 0383618a..00000000 --- a/website/translated_docs/nl/development_guidelines.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: "Style guidelines" ---- - -Home Assistant enforces strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. We automatically test every pull request as part of the linting process. - -Summary of the most relevant points: - -- Line length is limited to 79 characters (see below). -- Use 4 spaces per indentation level. We don't use tabs. -- Comments should be full sentences and end with a period. -- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered. -- Constants and the content of lists and dictionaries should be in alphabetical order. -- Avoid trailing whitespace but surround binary operators with a single space. -- Line separator should be set to `LF`. - -The maximum line length comes directly from the [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/#maximum-line-length), and is also used by the Python standard library. All code must pass these linting checks, and no exceptions will be made. There have already been numerous requests to increase the maximum line length, but after evaluating the options, the Home Assistant maintainers have decided to stay at 79 characters. This decision is final. - -Those points may require that you adjust your IDE or editor settings. - -## Our recommendations - -For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code unified. - -### Quotes - -Use single quotes `'` for single word and `"` for multiple words or sentences. - -```python -ATTR_WATERLEVEL = 'level' -CONF_ATTRIBUTION = "Data provided by the WUnderground weather service" -SENSOR_TYPES = { - 'alerts': ['Alerts', None], -} -``` - -### File headers - -The docstring in the file header should describe what the file is about. - -```python -"""Support for MQTT lights.""" -``` - -### Log messages - -There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. Try to avoid brackets and additional quotes around the output to make it easier for users to parse the log. A widely style is shown below but you are free to compose the messages as you like. - -```python -_LOGGER.error("No route to device: %s", self._resource) -``` - -```bash -2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18 -``` - -Don't print out wrong API keys, tokens, usernames, or passwords. Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` in anything else. - -### Ordering of imports - -Instead of order the imports manually, use [`isort`](https://github.com/timothycrosley/isort). - -```bash -$ pip3 install isort -$ isort homeassistant/components/sensor/fixer.py -``` - -### Use new style string formatting - -Prefer [new style string formatting](https://www.python.org/dev/peps/pep-3101/) over old. - -```python -"{} {}".format('New', 'style') -"%s %s" % ('Old', 'style') -``` - -Except when doing logging here the format is: - -```python -_LOGGER.info("Can't connect to the webservice %s at %s", string1, string2) -``` \ No newline at end of file diff --git a/website/translated_docs/nl/development_index.md b/website/translated_docs/nl/development_index.md deleted file mode 100644 index d0557fd3..00000000 --- a/website/translated_docs/nl/development_index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: "Starting with Development" -sidebar_label: Introduction ---- - -Home Assistant is built from the ground up to be easily extensible using integrations. In this section, we're focusing on how to develop integrations. - -Before you start, make sure that you have read up on the [Home Assistant architecture](architecture_index.md) so that you are familiar with the concepts that make up Home Assistant. - -If you run into trouble following this documentation, don't hesitate to join our #devs_backend channel on [Discord](https://www.home-assistant.io/join-chat/). \ No newline at end of file diff --git a/website/translated_docs/nl/development_submitting.md b/website/translated_docs/nl/development_submitting.md deleted file mode 100644 index 5f0bac56..00000000 --- a/website/translated_docs/nl/development_submitting.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Submit your work" ---- - -> Always base your Pull Requests of of the current **`dev`** branch, not `master`. - -Submit your improvements, fixes, and new features to Home Assistant one at a time, using GitHub [Pull Requests](https://help.github.com/articles/using-pull-requests). Here are the steps: - -1. From your fork's dev branch, create a new branch to hold your changes: - - `git checkout -b some-feature` - -2. Make your changes, create a [new platform](creating_platform_index.md), develop a [new component](creating_component_index.md), or fix [issues](https://github.com/home-assistant/home-assistant/issues). - -3. [Test your changes](development_testing.md) and check for style violations. - -4. If everything looks good according to these [musts](development_checklist.md), commit your changes: - - `git add .` - - `git commit -m "Add some-feature"` - - - Write a meaningful commit message and not only `Update` or `Fix`. - - Use a capital letter to start with your commit message. - - Don't prefix your commit message with `[bla.bla]` or `platform:`. - - Consider adding tests to ensure that your code works. - -5. Push your committed changes back to your fork on GitHub: - - `git push origin HEAD` - -6. Follow [these steps](https://help.github.com/articles/creating-a-pull-request/) to create your pull request. - - - On GitHub, navigate to the main page of the Home Assistant repository. - - In the "Branch" menu, choose the branch that contains your commits (from your fork). - - To the right of the Branch menu, click **New pull request**. - - Use the base branch dropdown menu to select the branch you'd like to merge your changes into, then use the compare branch drop-down menu to choose the topic branch you made your changes in. Make sure the Home Assistant branch matches with your forked branch (`dev`) else you will propose ALL commits between branches. - - Type a title and complete the provided description for your pull request. - - Click **Create pull request**. - -7. Check for comments and suggestions on your pull request and keep an eye on the [CI output](https://travis-ci.org/home-assistant/home-assistant/). \ No newline at end of file diff --git a/website/translated_docs/nl/development_testing.md b/website/translated_docs/nl/development_testing.md deleted file mode 100644 index 2b57f7e1..00000000 --- a/website/translated_docs/nl/development_testing.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: "Testing your code" ---- - -As it states in the [Style guidelines section](development_guidelines.md) all code is checked to verify the following: - -- All the unit tests pass -- All code passes the checks from the linting tools - -Local testing is done using Tox, which has been installed as part of running `script/setup` in the [virtual environment](development_environment.md). To start the tests, activate the virtual environment and simply run the command: - -```bash -$ tox -``` - -**Important:** Run `tox` before you create your pull request to avoid annoying fixes. - -Running Tox will run unit tests against the locally available Pythons, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one tox target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py36` runs unit tests only on Python 3.6. - -Tox uses virtual environments under the hood to create isolated testing environments. The tox virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell Tox to recreate the virtual environments. - -OSX users may see an `Error creating virtualenv` when runnng `tox`. If this occurs, install the [tox-venv](https://pypi.org/project/tox-venv/) package using the command `pip install tox-venv` and try again. - -### Adding new dependencies to test environment - -If you are working on tests for a component or platform and you need the dependencies available inside the Tox environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments. - -### Running single tests using Tox - -You can pass arguments via Tox to py.test to be able to run single test suites or test files. Replace `py36` with the Python version that you use. - -```bash -# Stop after the first test fails -$ tox -e py36 -- tests/test_core.py -x -# Run test with specified name -$ tox -e py36 -- tests/test_core.py -k test_split_entity_id -# Fail a test after it runs for 2 seconds -$ tox -e py36 -- tests/test_core.py --timeout 2 -# Show the 10 slowest tests -$ tox -e py36 -- tests/test_core.py --duration=10 -``` - -### Testing outside of Tox - -Running tox will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without Tox, you'll need to install the test dependencies into your Python environment: - -```bash -$ pip3 install -r requirements_test_all.txt -c homeassistant/package_constraints.txt -``` - -Now that you have all test dependencies installed, you can run tests on individual files: - -```bash -$ flake8 homeassistant/core.py -$ pylint homeassistant/core.py -$ pydocstyle homeassistant/core.py -$ py.test tests/test_core.py -``` - -You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script: - -```bash -$ script/lint -``` - -### Preventing Linter Errors - -Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them! - -```bash -$ pip3 install flake8 flake8-docstrings -$ flake8 --install-hook=git -``` - -The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8. - -### Notes on PyLint and PEP8 validation - -If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member. \ No newline at end of file diff --git a/website/translated_docs/nl/development_typing.md b/website/translated_docs/nl/development_typing.md deleted file mode 100644 index 81f153cd..00000000 --- a/website/translated_docs/nl/development_typing.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: "Adding type hints to your code" ---- - -Type hints in Python are static annotations of variables and functions, to let humans more easily understand the code. See the standard library [docs](https://docs.python.org/3/library/typing.html) and this PyCascades 2018 [talk](https://youtu.be/zKre4DKAB30). - -Type hints are not required for all modules at the moment in Home Assistant, but we aim to have complete coverage of the core modules. - -Adding type hints to an existing codebase can be a daunting task. To speed this up and help developers doing this, Instagram made the [`monkeytype`](https://pypi.org/project/MonkeyType/) program. It will analyze calls during runtime and try to assign the correct type hints to the code. - -See [this instagram blog post](https://instagram-engineering.com/let-your-code-type-hint-itself-introducing-open-source-monkeytype-a855c7284881) for a description of the workflow involved to use the monkeytype program. - -We've added a script to start a run of our test suite or a test module and tell the `monkeytype` program to analyze the run. - -### Basic workflow - -1. Run `script/monkeytype tests/path/to/your_test_module.py`. -2. Run `monkeytype stub homeassistant.your_actual_module`. -3. Look at output from the monkeytyped typing stub. If not totally bad, apply the stub to your module. You most likely will need to manually edit the typing in the last step. -4. Run `monkeytype apply homeassistant.your_actual_module`. -5. Check the diff and manually correct the typing if needed. Commit, push the branch and make a PR. - -**Note:** Applying a monkeytyped stub to a module that has existing typing annotations might error and not work. This tool is most useful for totally untyped modules. \ No newline at end of file diff --git a/website/translated_docs/nl/development_validation.md b/website/translated_docs/nl/development_validation.md deleted file mode 100644 index 9e7770a7..00000000 --- a/website/translated_docs/nl/development_validation.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: "Validate the input" ---- - -The `configuration.yaml` file contains the configuration options for components and platforms. We use [voluptuous](https://pypi.python.org/pypi/voluptuous) to make sure that the configuration provided by the user is valid. Some entries are optional or could be required to set up a platform or a component. Others must be a defined type or from an already-defined list. - -We test the configuration to ensure that users have a great experience and minimize notifications if something is wrong with a platform or component setup before Home Assistant runs. - -Besides [voluptuous](https://pypi.python.org/pypi/voluptuous) default types, many custom types are available. For an overview, take a look at the [config_validation.py](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/config_validation.py) helper. - -- Types: `string`, `byte`, and `boolean` -- Entity ID: `entity_id` and `entity_ids` -- Numbers: `small_float` and `positive_int` -- Time: `time`, `time_zone` -- Misc: `template`, `slug`, `temperature_unit`, `latitude`, `longitude`, `isfile`, `sun_event`, `ensure_list`, `port`, `url`, and `icon` - -To validate platforms using [MQTT](https://www.home-assistant.io/components/mqtt/), `valid_subscribe_topic` and `valid_publish_topic` are available. - -Some things to keep in mind: - -- Use the constants defined in `const.py` -- Import `PLATFORM_SCHEMA` from the integration you are integrating with and extend it. -- Preferred order is `required` first and `optional` second -- Default values for optional configuration keys need to be valid values. Don't use a default which is `None` like `vol.Optional(CONF_SOMETHING, default=None): cv.string`, set the default to `default=''` if required. - -### Snippets - -This section contains snippets for the validation we use. - -#### Default name - -It's common to set a default for a sensor if the user doesn't provide a name to use. - -```python -DEFAULT_NAME = 'Sensor name' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, -``` - -#### Limit the values - -You might want to limit the user's input to a couple of options. - -```python -DEFAULT_METHOD = 'GET' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): vol.In(['POST', 'GET']), -``` - -#### Port - -All port numbers are from a range of 1 to 65535. - -```python -DEFAULT_PORT = 993 - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, -``` - -#### Lists - -If a sensor has a pre-defined list of available options, test to make sure the configuration entry matches the list. - -```python -SENSOR_TYPES = { - 'article_cache': ('Article Cache', 'MB'), - 'average_download_rate': ('Average Speed', 'MB/s'), -} - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_MONITORED_VARIABLES, default=[]): - vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), -``` \ No newline at end of file diff --git a/website/translated_docs/nl/device_registry_index.md b/website/translated_docs/nl/device_registry_index.md deleted file mode 100644 index 394002ea..00000000 --- a/website/translated_docs/nl/device_registry_index.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Device Registry -sidebar_label: Introduction ---- - -The device registry is a registry where Home Assistant keeps track of devices. A device is represented in Home Assistant via one or more entities. For example, a battery-powered temperature and a humidity sensor might expose entities for temperature, humidity and battery level. - -![Device registry overview](/img/en/device_registry/overview.png) - -## What is a device? - -A device in Home Assistant represents a physical device that has its own control unit. The control unit itself does not have to be smart, but it should be in control of what happens. For example, an Ecobee thermostat with 4 room sensors equals 5 devices in Home Assistant, one for the thermostat including all sensors inside it, and one for each sensor. - -If you connect a sensor to another device to read some of its data, it should still be represented as two different devices. The reason for this is that the sensor could be moved to read the data of another device. - -> Although not currently available, we could consider offering an option to users to merge devices. - -## Device properties - -| Attribute | Description | -| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| id | Unique ID of device (generated by Home Assistant) | -| name | Name of this device | -| connections | A set of tuples of `(connection_type, connection identifier)`. Connection types are defined in the device registry module. | -| identifiers | Set of identifiers. They identify the device in the outside world. An example is a serial number. | -| manufacturer | The manufacturer of the device. | -| model | The model of the device. | -| config_entries | Config entries that are linked to this device. | -| sw_version | The firmware version of the device. | -| via_hub | Identifier of a device that routes messages between this device and Home Assistant. Examples of such devices are hubs. This is used to show device topology in Home Assistant. | -| area_id | The Area which the device is placed in. | - -## Defining devices - -> Entity device info is only read if the entity is loaded via a [config entry](config_entries_index.md). - -Each entity is able to define a device via the `device_info` property. This property is read when an entity is added to Home Assistant via a config entry. A device will be matched up with an existing device via supplied identifiers and connections, like serial numbers or MAC addresses. - -```python -# Inside a platform -class HueLight(LightEntity): - - @property - def device_info(self): - return { - 'identifiers': { - # Serial numbers are unique identifiers within a specific domain - (hue.DOMAIN, self.unique_id) - }, - 'name': self.name, - 'manufacturer': self.light.manufacturername, - 'model': self.light.productname, - 'sw_version': self.light.swversion, - 'via_hub': (hue.DOMAIN, self.api.bridgeid), - } - -``` - -Components are also able to register devices in the case that there are no entities representing them. An example is a hub that communicates with the lights. - -```python -# Inside a component -from homeassistant.helpers import device_registry as dr - -device_registry = await dr.async_get_registry(hass) - -device_registry.async_get_or_create( - config_entry=entry.entry_id, - connections={ - (dr.CONNECTION_NETWORK_MAC, config.mac) - }, - identifiers={ - (DOMAIN, config.bridgeid) - }, - manufacturer='Signify', - name=config.name, - model=config.modelid, - sw_version=config.swversion, -) -``` \ No newline at end of file diff --git a/website/translated_docs/nl/documentation_create_page.md b/website/translated_docs/nl/documentation_create_page.md deleted file mode 100644 index e1669a55..00000000 --- a/website/translated_docs/nl/documentation_create_page.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: "Create a new page" ---- - -For a platform or component page, the fastest way is to make a copy of an existing page and edit it. The [Component overview](https://www.home-assistant.io/components/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages. - -Please honor the [Standards](documentation_standards.md) we have for the documentation. - -If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers. - -```text ---- -layout: page -title: "Awesome Sensor" -description: "home-assistant.io web presence" -date: 2015-06-17 08:00 -sidebar: true -comments: false -sharing: true -footer: true -ha_release: "0.38" -ha_category: Sensor -ha_iot_class: "Local Polling" -ha_qa_scale: silver ---- - -Content... Written in markdown. - -### {% linkable_title Linkable Header %} -... -``` - -Please keep in mind that if the `date:` entry is in the future then the page will not show up. - -Additional keys for the file header: - -- `logo`: Please check the separate section below. -- `ha_release`: The release when the integration was included, e.g., "0.38". If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`. -- `ha_category`: This entry is used to group the integration on the [Components overview](https://www.home-assistant.io/components/). -- `ha_iot_class`: [IoT class](https://www.home-assistant.io/blog/2016/02/12/classifying-the-internet-of-things) is the classifier for the device's behavior. -- `ha_qa_scale`: [Quality scale](https://www.home-assistant.io/docs/quality_scale/) is the representation of the integration's quality. - -There are [pre-defined variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation. - -A couple of points to remember: - -- Document the needed steps to retrieve API keys or access token for the third party service or device if needed. -- Add screenshots to support the user where it makes sense. -- Add the type of the device(s) (incl. firmware) you have tested when you know that there are multiple out there. - -### Configuration - -Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file. - -The **Configuration Variables** section must use the `{% configuration %} ... {% endconfiguration %}` tag. - -```text -{% configuration %} -api_key: - description: The API key to access the service. - required: true - type: string -name: - description: Name to use in the frontend. - required: false - default: The default name to use in the frontend. - type: string -monitored_conditions: - description: Conditions to display in the frontend. - required: true - type: map - keys: - weather: - description: A human-readable text summary. - temperature: - description: The current temperature. -{% endconfiguration %} -``` - -Available keys: - -- **`description:`**: That the variable is about. -- **`required:`**: If the variable is required. - -```text -required: true #=> Required -required: false #=> Optional -required: inclusive #=> Inclusive -required: exclusive #=> Exclusive -required: any string here #=> Any string here -``` - -- **`type:`**: The type of the variable. Allowed entries: `boolean`, `string`, `integer`, `float`, `time`, `template`, `device_class`, `icon` or `map`/`list` (for a list of entries). For multiple possibilities use `[string, integer]`. If you use `map`/`list` then should define `keys:` (see the [`template` sensor](https://www.home-assistant.io/components/sensor.template/) for an example). If you use `boolean`, then `default:` must be defined. -- **`default:`**: The default value for the variable. - -### Embedding Code - -You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in back-ticks. - -When you're writing code that is to be executed on the terminal, prefix it with `$`. - -### Templates - -For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) [Jinja](http://jinja.pocoo.org/) is used. Check the [Documentation Standards](documentation_standards.md) for further details. - -If you are don't escape templates then they will be rendered and appear blank on the website. - -### HTML - -The direct usage of HTML is supported but not recommended. The note boxes are an exception. - -```html -

- You need to enable telnet on your router. -

-``` - -### Images, icons and logos - -The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent. - -| Type | Location | -|:----------- |:------------------------------ | -| logos | source/images/supported_brands | -| blog | source/images/blog | -| screenshots | source/images/components | - -Not everything (product, component, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/). - -### Linking From The Sidebar - -If you are adding a new page that requires linking from the sidebar, you need to edit the `docs_navigation.html` file in `source/_includes/asides/docs_navigation.html`. \ No newline at end of file diff --git a/website/translated_docs/nl/documentation_index.md b/website/translated_docs/nl/documentation_index.md deleted file mode 100644 index d196169c..00000000 --- a/website/translated_docs/nl/documentation_index.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "Documentation" ---- - -The user documentation is located at . This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. You work on your change and propose it via a Pull Request (PR). - -Once you've created a Pull Request (PR), you can see a preview of the proposed changes by clicking *Details* against Netlify checker in the checkers section of the PR as soon as deployment is complete. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process of working on the website is no different from working on Home Assistant itself. - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.3.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` (You might have to run this command as `sudo`). -- Fork the home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.io). -- In your home-assistant.io root directory, run `$ bundle` to install the gems you need. - -- Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` - -- Shortcut for Debian/Ubuntu: `$ sudo apt-get install ruby ruby-dev ruby-bundler ruby-json g++ zlib1g-dev && bundle` - -Then you can work on the documentation: - -- Run `bundle exec rake generate` to generate the very first preview. This will take a couple of minutes. -- Create/edit/update a page. The components/platforms documentation is located in `source/_components/`. `source/_docs/` contains the Home Assistant documentation itself. -- Test your changes to home-assistant.io locally: run `bundle exec rake preview` and navigate to . While this command is working, any changes to a file are automatically detected and will update the affected pages. You will have to manually reload them in the browser though. -- Create a Pull Request (PR) against the **next** branch of home-assistant.io if your documentation is a new feature, platform, or component. -- Create a Pull Request (PR) against the **current** branch of home-assistant.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -The site generated by `bundle exec rake` is only available locally. If you are developing on a headless machine, use port forwarding: - -```bash -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` - -## Speeding up site generation - -Every release we post long changelogs to the website. This slows down generation of the website significantly! We include some tools to temporarily exclude components and blog posts that you're not working on out of the way. - -```bash -bundle exec rake isolate[filename-of-blogpost-or-component] -``` - -When you're done working on the site, run the following command to move the pages back again: - -```bash -bundle exec rake integrate -``` \ No newline at end of file diff --git a/website/translated_docs/nl/documentation_standards.md b/website/translated_docs/nl/documentation_standards.md deleted file mode 100644 index d0ae54d1..00000000 --- a/website/translated_docs/nl/documentation_standards.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: "Standards" ---- - -To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation. - -## General Documentation - -* The language of the documentation should be American-English. -* Don't put two spaces after a period and avoid the "Oxford comma". -* There is no limit for the line length. You are allowed to write in a flowing text style. This will make it easier to use the GitHub online editor in the future. -* Be objective and not gender favoring, polarizing, race related or religion inconsiderate. -* The case of brand names, services, protocols, components and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select". -* All headings should use the `{% linkable_title %}` tag. -* Do not use ALL CAPITALS for emphasis - use italics instead. - -## Component and Platform Pages - -* The **Configuration Variables** section must use the `{% configuration %}` tag. -* Configuration variables must document the requirement status (`false` or `true`). -* Configuration variables must document the default value, if any. -* Configuration variables must document the accepted value types (see [Configuration variables details](documentation_create_page.md#configuration)). - * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`). -* Use YAML sequence syntax in the sample code if it is supported. -* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated. - * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`. - * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note. -* Component and platform names should be a link to their respective documentation pages. - -Example configuration block - -```yaml -{% configuration %} -some_key: - description: This is a description of what this key is for. - required: false - type: string - default: Optional default value - leave out if there isn't one -{% endconfiguration %} -``` - -## Templates - -* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the `{% raw %}` tag. -* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`. -* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)): - * `friendly_name` - * Single-line templates: - * `value_template` - * `level_template` - * `icon_template` - * Children of `data_template` -* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks): - * Strings inside of templates: - * States - * Entity IDs - * `unit_of_measurement` -* No whitespace around pipe character (`|`) for Jinja2 filters. -* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}). -* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}). -* Do not quote values for: - * `device_class` - * `platform` - * `condition` - * `service` - -## Renaming Pages - -It can happen that a component or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old component/platform name, to the page in a [note](/developers/documentation/create_page/#html). - -```text ---- -... -redirect_from: /getting-started/android/ ---- -``` - -Adding a redirect also applies if you move content around in the [documentation](/docs/). - -## Single vs. Double Quotation Marks - -Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required). - -### Examples - -#### Double Quotes Outside, Single Quotes Inside (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}" -``` - -#### Single Quotes Outside, Double Quotes Inside (Invalid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}' -``` - -#### Multi-Line Template (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: >- - {% if trigger.to_state.name == 'Dale\'s Bedroom' %} - Someone's in your base, killing your noobs! - {% else %} - It's just another door. - {% endif %} -``` \ No newline at end of file diff --git a/website/translated_docs/nl/entity_air_quality.md b/website/translated_docs/nl/entity_air_quality.md deleted file mode 100644 index 81c10f5c..00000000 --- a/website/translated_docs/nl/entity_air_quality.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Air Quality Entity -sidebar_label: Air Quality ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ---------------------------- | ----- | ------------ | --------------------------------------------- | -| particulate_matter_2_5 | float | **Required** | The particulate matter 2.5 (<= 2.5 μm) level. | -| particulate_matter_10 | float | **Required** | The particulate matter 10 (<= 10 μm) level. | -| particulate_matter_0_1 | float | `None` | The particulate matter 0.1 (<= 0.1 μm) level. | -| air_quality_index | float | `None` | The Air Quality Index (AQI). | -| ozone | float | `None` | The O3 (ozone) level. | -| carbon_monoxide | float | `None` | The CO (carbon monoxide) level. | -| carbon_dioxide | float | `None` | The CO2 (carbon dioxide) level. | -| sulphur_dioxide | float | `None` | The SO2 (sulphur dioxide) level. | -| nitrogen_oxide | float | `None` | The N2O (nitrogen oxide) level. | -| nitrogen_monoxide | float | `None` | The NO (nitrogen monoxide) level. | -| nitrogen_dioxide | float | `None` | The NO2 (nitrogen dioxide) level. | -| volatile_organic_compounds | float | `None` | The volatile organic compounds (VOC) level. | - -Properties have to follow the units defined in the `unit_system`. \ No newline at end of file diff --git a/website/translated_docs/nl/entity_alarm_control_panel.md b/website/translated_docs/nl/entity_alarm_control_panel.md deleted file mode 100644 index 9dc91192..00000000 --- a/website/translated_docs/nl/entity_alarm_control_panel.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Alarm Control Panel Entity -sidebar_label: Alarm Control Panel ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ----------- | ------ | ------------ | --------------------------------------------------------- | -| state | string | **Required** | One of the states listed in the **states** section. | -| code_format | string | `None` | One of the states listed in the **code formats** section. | -| changed_by | string | `None` | Last change triggered by. | - -### States - -| Value | Description | -| ---------------------- | ------------------------------------------- | -| `disarmed` | The alarm is disarmed (`off`). | -| `armed_home` | The alarm is armed in home mode. | -| `armed_away` | The alarm is armed in away mode. | -| `armed_night` | The alarm is armed in night mode. | -| `armed_custom_bypass`  | The alarm is armed in bypass mode. | -| `pending` | The alarm is pending (towards `triggered`). | -| `arming` | The alarm is arming. | -| `disarming` | The alarm is disarming. | -| `triggered` | The alarm is triggered. | - -### Code Formats - -| Value | Description | -| ------ | ------------------------------------------------- | -| None | No code required. | -| Number | Code is a number (Shows ten-key pad on frontend). | -| Any | Code is a string. | - -## Methods - -### Alarm Disarm - -Send disarm command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_disarm(self, code=None) -> None: - """Send disarm command.""" - - async def async_alarm_disarm(self, code=None) -> None: - """Send disarm command.""" -``` - -### Alarm Arm Home - -Send arm home command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_home(self, code=None) -> None: - """Send arm home command.""" - - def async_alarm_arm_home(self, code=None) -> None: - """Send arm home command.""" -``` - -### Alarm Arm Away - -Send arm away command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_away(self, code=None) -> None: - """Send arm away command.""" - - def async_alarm_arm_away(self, code=None) -> None: - """Send arm away command.""" -``` - -### Alarm Arm Night - -Send arm night command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_night(self, code=None) -> None: - """Send arm night command.""" - - def async_alarm_arm_night(self, code=None) -> None: - """Send arm night command.""" -``` - -### Alarm Trigger - -Send alarm trigger command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_trigger(self, code=None) -> None: - """Send alarm trigger command.""" - - def async_alarm_trigger(self, code=None) -> None: - """Send alarm trigger command.""" -``` - -### Alarm Custom Bypass - -Send arm custom bypass command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_custom_bypass(self, code=None) -> None: - """Send arm custom bypass command.""" - - def async_alarm_arm_custom_bypass(self, code=None) -> None: - """Send arm custom bypass command.""" -``` \ No newline at end of file diff --git a/website/translated_docs/nl/entity_binary_sensor.md b/website/translated_docs/nl/entity_binary_sensor.md deleted file mode 100644 index 1a791ddb..00000000 --- a/website/translated_docs/nl/entity_binary_sensor.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Binary Sensor Entity -sidebar_label: Binary Sensor ---- - -A binary sensor is a sensor that can only have two states. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------ | ------- | ------------ | -------------------------------------------- | -| is_on | boolean | **Required** | If the binary sensor is currently on or off. | -| device_class | string | `None` | Type of binary sensor. | - -### Available device classes - -| Value | Description | -| ------------ | ------------------------------------------------------ | -| battery | On means low, Off means normal. | -| cold | On means cold, Off means normal. | -| connectivity | On means connected, Off means disconnected. | -| door | On means open, Off means closed. | -| garage_door | On means open, Off means closed. | -| gas | On means gas detected, Off means no gas (clear). | -| heat | On means hot, Off means normal. | -| light | On means light detected, Off means no light. | -| lock | On means open (unlocked), Off means closed (locked). | -| moisture | On means wet, Off means dry. | -| motion | On means motion detected, Off means no motion (clear). | -| moving | On means moving, Off means not moving (stopped). | -| occupancy | On means occupied, Off means not occupied (clear). | -| opening | On means open, Off means closed. | -| plug | On means plugged in, Off means unplugged. | -| power | On means power detected, Off means no power. | -| presence | On means home, Off means away. | -| problem | On means problem detected, Off means no problem (OK). | -| safety | On means unsafe, Off means safe. | -| smoke | On means smoke detected, Off means no smoke (clear). | -| sound | On means sound detected, Off means no sound (clear). | -| vibration | On means vibration detected, Off means no vibration. | -| window | On means open, Off means closed. | \ No newline at end of file diff --git a/website/translated_docs/nl/entity_climate.md b/website/translated_docs/nl/entity_climate.md deleted file mode 100644 index 477e1bcd..00000000 --- a/website/translated_docs/nl/entity_climate.md +++ /dev/null @@ -1,230 +0,0 @@ ---- -title: Climate Entity -sidebar_label: Climate ---- - -> A climate entity is a device that controls temperature, humidity, or fans, such as A/C systems and humidifiers. Derive entity platforms from [`homeassistant.components.climate.ClimateDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/climate/__init__.py) - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------------------- | ---------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | -| current_fan_mode | string | None | Returns the current fan mode. | -| current_hold_mode | string | None | The current hold mode, e.g., home, away, temp. | -| current_humidity | float | None | The current humidity. | -| current_operation | string | None | The current operation (e.g. heat, cool, idle). Used to determine `state`. | -| current_swing_mode | string | None | Returns the fan setting. | -| current_temperature | float | None | The current temperature. | -| fan_list | list | None | Returns the list of available fan modes. | -| is_aux_heat_on | bool | None | Returns True if an auxiliary heater is on. | -| is_away_mode_on | bool | None | Return true if away mode is on. | -| is_on | bool | None | Returns True if device is on. Used to determine `state`. | -| max_humidity | int | `DEFAULT_MAX_HUMIDITY` (value == 99) | Returns the maximum humidity. | -| max_temp | int | `DEFAULT_MAX_TEMP` (value == 35) | Returns the maximum temperature. | -| min_humidity | int | `DEFAULT_MIN_HUMIDITY` (value == 30) | Returns the minimum humidity. | -| min_temp | int | `DEFAULT_MIN_TEMP` (value == 7) | Returns the minimum temperature. | -| operation_list | list | None | List of available operation modes. | -| precision | float | PRECISION_WHOLE | The precision of the temperature in the system: tenths for TEMP_CELSIUS, whole number otherwise. | -| state | string | None | Returns the current state. | -| state_attributes | dictionary | N/A | The optional state attributes: current temperature, minimum temperature, maximum temperature, and target temperature. | -| supported_features | list | `NotImplementedError()` | Returns list of supported features. | -| swing_list | list | None | Returns the list of available swing modes. | -| target_humidity | float | None | The target humidity. | -| target_temperature | float | None | The temperature currently set to be reached. | -| target_temperature_high | float | None | The upper bound target temperature | -| target_temperature_low | float | None | The lower bound target temperature | -| target_temperature_step | float | None | The supported step of target temperature | -| temperature_unit | string | `NotImplementedError` | The unit of temperature measurement for the system (e.g. Celsius). | - -### States - -| Name | Description | -| ---------------- | ------------------------------ | -| STATE_HEAT | The device is set to heat. | -| STATE_COOL | The device is set to cool. | -| STATE_IDLE | The device is idle. | -| STATE_AUTO | The device is set to auto. | -| STATE_MANUAL | The device is set to manual. | -| STATE_DRY | The device is set to dry. | -| STATE_FAN_ONLY | The device is set to fan-only. | -| STATE_ECO | The device is set to eco-mode. | - -### Supported features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Name | Description | -| --------------------------------- | ------------------------------------------------------ | -| SUPPORT_TARGET_TEMPERATURE | The device supports a target temperature. | -| SUPPORT_TARGET_TEMPERATURE_HIGH | The device supports an upper bound target temperature. | -| SUPPORT_TARGET_TEMPERATURE_LOW | The device supports a lower bound target temperature. | -| SUPPORT_TARGET_HUMIDITY | The device supports a target humidity. | -| SUPPORT_TARGET_HUMIDITY_HIGH | The device supports an upper bound target humidity. | -| SUPPORT_TARGET_HUMIDITY_LOW | The device supports a lower bound target humidity. | -| SUPPORT_FAN_MODE | The device supports fan modes. | -| SUPPORT_OPERATION_MODE | The device supports operation modes. | -| SUPPORT_HOLD_MODE | The device supports hold modes. | -| SUPPORT_SWING_MODE | The device supports swing modes. | -| SUPPORT_AWAY_MODE | The device supports away mode. | -| SUPPORT_AUX_HEAT | The device supports auxiliary heaters. | -| SUPPORT_ON_OFF | The device supports on/off states. | - -## Methods - -### Set fan mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_fan_mode(self, fan_mode): - """Set new target fan mode.""" - - async def async_set_fan_mode(self, fan_mode): - """Set new target fan mode.""" -``` - -### Set hold mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_hold_mode(self, hold_mode): - """Set new target hold mode.""" - - async def async_set_hold_mode(self, hold_mode): - """Set new target hold mode.""" -``` - -### Set humidity - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_humidity(self, humidity): - """Set new target humidity.""" - - async def async_set_humidity(self, humidity): - """Set new target humidity.""" -``` - -### Set operation mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_operation_mode(self, operation_mode): - """Set new target operation mode.""" - - async def async_set_operation_mode(self, operation_mode): - """Set new target operation mode.""" -``` - -### Set swing mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_swing_mode(self, swing_mode): - """Set new target swing operation.""" - - async def async_set_swing_mode(self, swing_mode): - """Set new target swing operation.""" -``` - -### Set temperature - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_temperature(self, **kwargs): - """Set new target temperature.""" - - async def async_set_temperature(self, **kwargs): - """Set new target temperature.""" -``` - -### Turn auxiliary heater on - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_aux_heat_on(self): - """Turn auxiliary heater on.""" - - async def async_turn_aux_heat_on(self): - """Turn auxiliary heater on.""" -``` - -### Turn auxiliary heater off - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_aux_heat_off(self): - """Turn auxiliary heater off.""" - - async def async_turn_aux_heat_off(self): - """Turn auxiliary heater off.""" -``` - -### Turn away mode on - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_away_mode_on(self): - """Turn away mode on.""" - - async def async_turn_away_mode_on(self): - """Turn away mode on.""" -``` - -### Turn away mode off - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_away_mode_off(self): - """Turn away mode off.""" - - async def async_turn_away_mode_off(self): - """Turn away mode off.""" -``` - -### Turn the device on - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_on(self): - """Turn device on.""" - - async def async_turn_on(self): - """Turn device on.""" -``` - -### Turn the device off - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_off(self): - """Turn device off.""" - - async def async_turn_off(self): - """Turn device off.""" -``` \ No newline at end of file diff --git a/website/translated_docs/nl/entity_cover.md b/website/translated_docs/nl/entity_cover.md deleted file mode 100644 index 9fe8a9ce..00000000 --- a/website/translated_docs/nl/entity_cover.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: Cover Entity -sidebar_label: Cover ---- - -A cover entity is a device that controls an opening or cover, such as a garage door and window shade. Derive entity platforms from [`homeassistant.components.cover.CoverDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/cover/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -### Platform Properties (to be implemented by deriving platform classes) - -| Name | Type | Default | Description | -| ----------------------------- | ---- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| current_cover_position | int | None | The current position of cover where 0 means closed and 100 is fully open. Required with `SUPPORT_SET_POSITION`. | -| current_cover_tilt_position | int | None | The current tilt position of the cover where 0 means closed/no tilt and 100 means open/maximum tilt. Required with `SUPPORT_SET_TILT_POSITION` | -| is_opening | bool | None | If the cover is opening or not. Used to determine `state`. | -| is_closing | bool | None | If the cover is closing or not. Used to determine `state`. | -| is_closed | bool | `NotImplementedError()` | If the cover is closed or not. if the state is unknown, return `None`. Used to determine `state`. | - -### Entity Properties (base class properties which may be overriden) - -| Name | Type | Default | Description | -| ------------------ | ------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | -| device_class | string | None | Describes the type/class of the cover. Must be `None` or one of the valid values from the table below. | -| supported_features | int (bitwise) | Value determined from `current_cover_position` and `current_cover_tilt_position` | Describes the supported features. See the related table below for details. | - -### Device Classes - -| Constant | Description | -| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `DEVICE_CLASS_AWNING` | Control of an awning, such as an exterior retractible window, door, or patio cover. | -| `DEVICE_CLASS_BLIND` | Control of blinds, which are linked slats that expand or collapse to cover an opening or may be tilted to partially cover an opening, such as window blinds. | -| `DEVICE_CLASS_CURTAIN` | Control of curtains or drapes, which is often fabric hung above a window or door that can be drawn open. | -| `DEVICE_CLASS_DAMPER` | Control of a mechanical damper that reduces air flow, sound, or light. | -| `DEVICE_CLASS_DOOR` | Control of a door or gate that provides access to an area. | -| `DEVICE_CLASS_GARAGE` | Control of a garage door that provides access to a garage. | -| `DEVICE_CLASS_SHADE` | Control of shades, which are a continous plane of material or connected cells that expanded or collapsed over an opening, such as window shades. | -| `DEVICE_CLASS_SHUTTER` | Control of shutters, which are linked slats that swing out/in to cover an opening or may be tilted to partially cover an opening, such as indoor or exterior window shutters. | -| `DEVICE_CLASS_WINDOW` | Control of a physical window that opens and closes or may tilt. | - -### States - -| Constant | Description | -| --------------- | --------------------------------------------------------------- | -| `STATE_OPENING` | The cover is in the process of opening to reach a set position. | -| `STATE_OPEN` | The cover has reached the open position. | -| `STATE_CLOSING` | The cover is in the process of closing to reach a set position. | -| `STATE_CLOSED` | The cover has reach the closed position. | - -### Supported Features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Constant | Description | -| --------------------------- | -------------------------------------------------------------------------------- | -| `SUPPORT_OPEN` | The cover supports being opened. | -| `SUPPORT_CLOSE` | The cover supports being closed. | -| `SUPPORT_SET_POSITION` | The cover supports moving to a specific position between opened and closed. | -| `SUPPORT_STOP` | The cover supports stopping the current action (open, close, set position) | -| `SUPPORT_OPEN_TILT` | The cover supports being tilting open. | -| `SUPPORT_CLOSE_TILT` | The cover supports being tilting closed. | -| `SUPPORT_SET_TILT_POSITION` | The cover supports moving to a specific tilt position between opened and closed. | -| `SUPPORT_STOP_TILT` | The cover supports stopping the current tilt action (open, close, set position) | - -## Methods - -### Open cover - -Only implement this method if the flag `SUPPORT_CLOSE` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover(self, **kwargs): - """Open the cover.""" - - async def async_open_cover(self, **kwargs): - """Open the cover.""" -``` - -### Close cover - -Only implement this method if the flag `SUPPORT_CLOSE` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover(self, **kwargs): - """Close cover.""" - - async def async_close_cover(self, **kwargs): - """Close cover.""" -``` - -### Set cover position - -Only implement this method if the flag `SUPPORT_SET_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" - - async def async_set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" - -``` - -### Stop cover - -Only implement this metohd if the flag `SUPPORT_STOP` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover(self, **kwargs): - """Stop the cover.""" -``` - -### Open cover tilt - -Only implement this method if the flag `SUPPORT_OPEN_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" - - async def async_open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" -``` - -### Close cover tilt - -Only implement this method if the flag `SUPPORT_CLOSE_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" - - async def async_close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" -``` - -### Set cover tilt position - -Only implement this method if the flag `SUPPORT_SET_TILT_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" - - async def async_set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" -``` - -### Stop cover tilt - -Only implement this method if the flag `SUPPORT_STOP_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover_tilt(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover_tilt(self, **kwargs): - """Stop the cover.""" -``` \ No newline at end of file diff --git a/website/translated_docs/nl/entity_fan.md b/website/translated_docs/nl/entity_fan.md deleted file mode 100644 index 27b6f7dc..00000000 --- a/website/translated_docs/nl/entity_fan.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Fan Entity -sidebar_label: Fan ---- - -A fan entity is a device that controls the different vectors of your fan such as speed, direction and oscillation. Derive enitity platforms from ['homeassistant.components.fan.FanDevice'](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/fan/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------------ | ------- | ------- | --------------------------------------- | -| current_direction | str | None | Return the current direction of the fan | -| is_on | boolean | None | Return true if the entity is on | -| speed | str | None | Return the current speed | -| speed_list | list | None | Get the list of available speeds | -| state_attributes | dict | None | Return optional state attributes | -| supported_features | int | None | Flag supported features | - -## Supported Features - -| Constant | Description | -| --------------------- | ---------------------------------------------- | -| 'SUPPORT_DIRECTION' | The fan supports changing the direction of it. | -| 'SUPPORT_SET_SPEED' | The fan supports setting the speed. | -| 'SUPPORT_OSCILLATE' | The fan supports oscillation. | - -## Methods - -### Set direction - -Only implement this method if the flag `SUPPORT_DIRECTION` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def set_direction(self, direction: str) -> None: - """Set the direction of the fan.""" - - async def async_set_direction(self, direction: str): - """Set the direction of the fan.""" -``` - -### Set speed - -Only implement this method if the flag `SUPPORT_SET_SPEED` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def set_speed(self, speed: str) -> None: - """Set the speed of the fan.""" - - async def async_set_speed(self, speed: str): - """Set the speed of the fan.""" -``` - -### Turn on - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def turn_on(self, speed: str = None, **kwargs) -> None: - """Turn on the fan.""" - - async def async_turn_on(self, speed: str = None, **kwargs): - """Turn on the fan.""" -``` - -### Oscillate - -Only implement this method if the flag `SUPPORT_OSCILLATE` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def oscillate(self, oscillating: bool) -> None: - """Oscillate the fan.""" - - def async_oscillate(self, oscillating: bool): - """Oscillate the fan.""" -``` \ No newline at end of file diff --git a/website/translated_docs/nl/entity_index.md b/website/translated_docs/nl/entity_index.md deleted file mode 100644 index 5385e078..00000000 --- a/website/translated_docs/nl/entity_index.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Entity -sidebar_label: Introduction ---- - -Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating. - -Below is an example switch entity that keeps track of their state in memory. - -```python -from homeassistant.components.switch import SwitchDevice - -class MySwitch(SwitchDevice): - - def __init__(self): - self._is_on = False - - @property - def name(self): - """Name of the device.""" - return 'My Switch' - - @property - def is_on(self): - """If the switch is currently on or off.""" - return self._is_on - - def turn_on(self, **kwargs): - """Turn the switch on.""" - self._is_on = True - - def turn_off(self, **kwargs): - """Turn the switch off.""" - self._is_on = False -``` - -That's all there is to it to build a switch entity! Continue reading to learn more or check out the [video tutorial](https://youtu.be/Cfasc9EgbMU?t=737). - -## Updating the entity - -An entity represents a device. There are various strategies to keep your entity in sync with the state of the device, the most popular one being polling. - -### Polling - -With polling, Home Assistant will ask the entity from time to time (depending on the update interval of the component) to fetch the latest state. Home Assistant will poll an entity when the `should_poll` property returns `True` (the default value). You can either implement your update logic using `update()` or the async method `async_update()`. This method should fetch the latest state from the device and store it in an instance variable for the properties to return it. - -### Subscribing to updates - -When you subscribe to updates, your code is responsible for letting Home Assistant know that an update is available. Make sure you have the `should_poll` property return `False`. - -Whenever you receive new state from your subscription, you can tell Home Assistant that an update is available by calling `schedule_update_ha_state()` or async callback `async_schedule_update_ha_state()`. Pass in the boolean `True` to the method if you want Home Assistant to call your update method before writing the update to Home Assistant. - -## Generic properties - -The entity base class has a few properties that are common among all entities in Home Assistant. These can be added to any entity regardless of the type. All these properties are optional and don't need to be implemented. - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| assumed_state | boolean | `False` | Return `True` if the state is based on our assumption instead of reading it from the device. | -| available | boolean | `True` | Indicate if Home Assistant is able to read the state and control the underlying device. | -| device_state_attributes | dict | `None` | Extra information to store in the state machine. It needs to be information that further explains the state, it should not be static information like firmware version. See [below](entity_index.md#standard_attributes) for details of standard attributes. | -| entity_picture | URL | `None` | Url of a picture to show for the entity. | -| name | string | `None` | Name of the entity | -| should_poll | boolean | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](#methods). | -| unique_id | string | `None` | A unique identifier for this entity. Needs to be unique within a platform (ie `light.hue`). Should not be configurable by the user or be changeable. [Learn more.](entity_registry_index.md#unique-id-requirements) | - -## Advanced properties - -The following properties are also available on entities. However, they are for advanced use only and should be used with caution. - -| Name | Type | Default | Description | -| ------------ | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| force_update | boolean | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine. | -| hidden | boolean | `False` | Indicate if the entity should not be shown on the frontend. | -| icon | icon | `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all devices. | - -## Standard attributes - -The following `device_state_attributes` are considered standard and should follow the convention below. The constant should be imported from `homeassistant/const.py`. - -| Name | Type | Unit | Constant | Description | -| ---------------- | ------- | ---- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| battery_charging | boolean | N/A | `ATTR_BATTERY_CHARGING` | Battery charging status of the entity, shown as a boolean `true` or `false`. If charging is not supported, then this attribute should not be created. | -| battery_level | integer | % | `ATTR_BATTERY_LEVEL` | Battery level of the entity, shown as an integer percentage between 0-100. | - -## Lifecycle hooks - -Use these lifecycle hooks to execute code when certain events happen to the entity. All lifecycle hooks are async methods. - -### `async_added_to_hass()` - -Called when an entity has their entity_id and hass object assigned, before it is written to the state machine for the first time. Example uses: restore the state, subscribe to updates or set callback/dispatch function/listener. - -### `async_will_remove_from_hass()` - -Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates. - -## Changing the entity model - -If you want to add a new feature to an entity or any of its subtypes (light, switch, etc), you will need to propose it first in our [architecture repo](https://github.com/home-assistant/architecture/issues). Only additions will be considered that are common features among various vendors. \ No newline at end of file diff --git a/website/translated_docs/nl/entity_light.md b/website/translated_docs/nl/entity_light.md deleted file mode 100644 index 1b3d6561..00000000 --- a/website/translated_docs/nl/entity_light.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Light Entity -sidebar_label: Light ---- - - -A light entity is a device that controls the brightness, RGB value,color temperature and effects of a light source. - -## Properties - -| Name | Type | Default | Description | -| ------------------ | ------ | ------- | --------------------------------------------------------- | -| brightness | int | None | Return the brightness of this light between 0..255 | -| color_temp | int | None | Return the CT color value in mireds. | -| effect | String | None | Return the current effect. | -| effect_list | list | None | Return the list of supported effects. | -| hs_color | list | None | Return the hue and saturation color value [float, float]. | -| is_on | bool | bool | Returns if the light entity is on or not. | -| max_minreds | int | int | Return the warmest color_temp that this light supports. | -| min_mireds | int | int | Return the coldest color_temp that this light supports. | -| supported_features | int | int | Flag supported features. | -| white_value | int | None | Return the white value of this light between 0..255. | - -## Support Feature - -| Constant | Description | -| --------------------- | --------------------------------------------------------------------- | -| `SUPPORT_BRIGHTNESS` | Controls the brightness of a light source | -| `SUPPORT_COLOR` | Controls the color a light source shows | -| `SUPPORT_COLOR_TEMP` | Controls the representation a light source shows based on temperature | -| `SUPPORT_EFFECT` | Controls the effect a light source shows | -| `SUPPORT_FLASH` | Controls the duration of a flash a light source shows | -| `SUPPORT_TRANSITION` | Controls the duration of transitions between color and effects | -| `SUPPORT_WHITE_VALUE` | Controls the white light a light source shows. | - -## Methods - -# Turn on Light Device - -```python -class MyLightDevice(LightDevice): - def turn_on(self, **kwargs): - """Turn the device on.""" - - async def async_turn_on(self, **kwargs): - """Turn device on.""" - -``` - -# Turn Off Light Device - -```python -class MyLightDevice(LightDevice): - - def turn_off(self, **kwargs): - """Turn the device off.""" - - async def async_turn_off(self, **kwargs): - """Turn device off.""" - -``` \ No newline at end of file diff --git a/website/translated_docs/nl/entity_lock.md b/website/translated_docs/nl/entity_lock.md deleted file mode 100644 index 7983db21..00000000 --- a/website/translated_docs/nl/entity_lock.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Lock Entity -sidebar_label: Lock ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ---- | ---- | ------- | ----------- | -| | | | | - -## Methods \ No newline at end of file diff --git a/website/translated_docs/nl/entity_media_player.md b/website/translated_docs/nl/entity_media_player.md deleted file mode 100644 index ab327f05..00000000 --- a/website/translated_docs/nl/entity_media_player.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Media Player Entity -sidebar_label: Media Player ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| --------------------------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------- | -| sound_mode | string | None | The current sound mode of the media player | -| sound_mode_list | list | None | Dynamic list of available sound modes (set by platform, empty means sound mode not supported) | -| source | string | None | The currently selected input source for the media player. | -| source_list | list | None | The list of possible input sources for the media player. (This list should contain human readable names, suitible for frontend display) | -| media_image_url | string | None | URL that represents the current image. | -| media_image_remotely_accessible | boolean | False | Return `True` if property `media_image_url` is accessible outside of the home network. | -| device_class | string | `None` | Type of binary sensor. | - -## Methods - -### Select sound mode - -Optional. Switch the sound mode of the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - def async_select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - -### Select source - -Optional. Switch the selected input source for the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_source(self, source): - """Select input source.""" - - def async_select_source(self, source): - """Select input source.""" - - -### Mediatype - -Required. Returns one of the defined constants from the below list that matches the mediatype - -| CONST | -| --------------------- | -| MEDIA_TYPE_MUSIC | -| MEDIA_TYPE_TVSHOW | -| MEDIA_TYPE_MOVIE | -| MEDIA_TYPE_VIDEO | -| MEDIA_TYPE_EPISODE | -| MEDIA_TYPE_CHANNEL | -| MEDIA_TYPE_PLAYLIST | -| MEDIA_TYPE_IMAGE | -| MEDIA_TYPE_URL | -| MEDIA_TYPE_GAME | -| MEDIA_TYPE_APP | - - class MyMediaPlayer(MediaPlayerDevice): - # Implement the following method. - - def media_content_type(self): - """Content type of current playing media.""" - - -### Available device classes - -Optional. What type of media device is this. It will possibly map to google device types. - -| Value | Description | -| ------- | ----------------------------------------- | -| tv | Device is a television type device. | -| speaker | Device is speakers or stereo type device. | \ No newline at end of file diff --git a/website/translated_docs/nl/entity_registry_index.md b/website/translated_docs/nl/entity_registry_index.md deleted file mode 100644 index aa346829..00000000 --- a/website/translated_docs/nl/entity_registry_index.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Entity Registry -sidebar_label: Introduction ---- - -The entity registry is a registry where Home Assistant keeps track of entities. Any entity that is added to Home Assistant and has a unique ID will be registered in the registry. - -Being registered has the advantage that the same entity will always get the same entity ID. It will also prevent other entities from using that entity ID. - -A user is also able to override the name of an entity in the entity registry. When set, the name of the entity registry is used in favor of the name the device might give itself. - -## Unique ID requirements - -An entity is looked up in the registry based on a combination of the plaform type (e.g., `light`), and the integration name (domain) (ie hue) and the unique ID of the entity. It is therefore very important that the unique ID is unique! It is also important that it is not possible for the user to change the unique ID, because that means it will lose all its settings related to it. - -Good sources for a unique ID: - -- Serial number of a device -- MAC address of a device -- latitude/longitude - -If a device has a single serial but provides multiple entities, combine the serial with unique identifiers for the entities. For example, if a device measures both temperature and humidity, you can uniquely identify the entities using `{serial}-{sensor_type}`. \ No newline at end of file diff --git a/website/translated_docs/nl/entity_remote.md b/website/translated_docs/nl/entity_remote.md deleted file mode 100644 index b4a0251d..00000000 --- a/website/translated_docs/nl/entity_remote.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Remote Entity -sidebar_label: Remote ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ---- | ---- | ------- | ----------- | -| | | | | - -## Methods \ No newline at end of file diff --git a/website/translated_docs/nl/entity_sensor.md b/website/translated_docs/nl/entity_sensor.md deleted file mode 100644 index 6a7e6307..00000000 --- a/website/translated_docs/nl/entity_sensor.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Sensor Entity -sidebar_label: Sensor ---- - -A sensor is a read-only entity that provides some information. Information has a value and optionally, a unit of measurement. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| --------------------- | ------ | ------------ | -------------------------------------------------------- | -| state | string | **Required** | The value of the sensor. | -| unit_of_measurement | string | `None` | The unit of measurement that the sensor is expressed in. | -| device_class | string | `None` | Type of sensor. | - -### Available device classes - -If specifying a device class, your sensor entity will need to also return the correct unit of measurement. - -| Type | Unit | Description | -| --------------- | -------- | -------------------------- | -| battery | % | % of battery that is left. | -| humidity | % | % of humidity in the air. | -| illuminance | lx/lm | Light level. | -| signal_strength | dB/dBm | Signal strength. | -| temperature | °C/°F | Temperature. | -| timestamp | ISO8601 | Timestamp. | -| power | W,kW | Power. | -| pressure | hPa,mbar | Pressure. | \ No newline at end of file diff --git a/website/translated_docs/nl/entity_switch.md b/website/translated_docs/nl/entity_switch.md deleted file mode 100644 index 14039422..00000000 --- a/website/translated_docs/nl/entity_switch.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Switch Entity -sidebar_label: Switch ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------------ | ------- | ------------ | ----------------------------------------------------------------------- | -| is_on | boolean | **Required** | If the switch is currently on or off. | -| current_power_w | float | `None` | The current power usage in W. | -| today_energy_kwh | float | `None` | Total energy usage in kWh. | -| is_standby | boolean | `None` | Indicate if the device connected to the switch is currently in standby. | - -## Methods - -### Turn On - -Turn the switch on. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def turn_on(self, **kwargs) -> None: - """Turn the entity on.""" - - async def async_turn_on(self, **kwargs): - """Turn the entity on.""" - -``` - -### Turn Off - -Turn the switch off. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def turn_off(self, **kwargs): - """Turn the entity off.""" - - async def async_turn_off(self, **kwargs): - """Turn the entity off.""" -``` - -### Toggle - -Optional. If not implemented will default to checking what method to call using the `is_on` property. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def toggle(self, **kwargs): - """Toggle the entity.""" - - async def async_toggle(self, **kwargs): - """Toggle the entity.""" -``` - -### Available device classes - -Optional. What type of device this. It will possibly map to google device types. - -| Value | Description | -| ------ | ----------------------------------------- | -| outlet | Device is an outlet for power. | -| switch | Device is switch for some type of entity. | \ No newline at end of file diff --git a/website/translated_docs/nl/entity_vacuum.md b/website/translated_docs/nl/entity_vacuum.md deleted file mode 100644 index b947d3df..00000000 --- a/website/translated_docs/nl/entity_vacuum.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Vacuum Entity -sidebar_label: Vacuum ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| -------------------- | ------ | ------------------------------- | --------------------------------------------------- | -| name | string | **Required** | Name of the device. | -| state | string | **Required** | One of the states listed in the states section. | -| battery_level | int | `none` | Current battery level. | -| battery_icon | string | function | Battery icon to show in UI. | -| cleaning_mode | string | `none` | The current cleaning mode. | -| cleaning_mode_list | list | `NotImplementedError()` | List of available fan speeds and cleaning modes. | -| error | string | **Required** with `STATE_ERROR` | An error message if the vacuum is in `STATE_ERROR`. | - -## States - -| State | Description | -| ----------------- | ------------------------------------------------------------------------------------------------------- | -| `STATE_CLEANING` | The vacuum is currently cleaning. | -| `STATE_DOCKED` | The vacuum is currently docked, it is assumed that docked can also mean charging. | -| `STATE_PAUSED` | The vacuum was cleaning but was paused without returning to the dock. | -| `STATE_IDLE` | The vacuum is not paused, not docked and does not have any errors. | -| `STATE_RETURNING` | The vacuum is done cleaning and is currently returning to the dock, but not yet docked. | -| `STATE_ERROR` | The vacuum encountered an error while cleaning, the error can be specified as a property on the entity. | - -## Methods - -### `turn_on` or `async_turn_on` - -Turn the vacuum on and start cleaning. - -### `turn_off`or `async_turn_off` - -Turn the vacuum off stopping the cleaning and returning home. - -### `return_to_base` or `async_return_to_base` - -Set the vacuum cleaner to return to the dock. - -### `stop` or `async_stop` - -Stop the vacuum cleaner, do not return to base. - -### `clean_spot` or `async_clean_spot` - -Perform a spot clean-up. - -### `locate` or `async_locate` - -Locate the vacuum cleaner. - -### `set_cleaning_mode` or `async_set_cleaning_mode` - -Set the cleaning mode. - -### `send_command` or `async_send_command` - -Send a command to a vacuum cleaner. \ No newline at end of file diff --git a/website/translated_docs/nl/entity_water_heater.md b/website/translated_docs/nl/entity_water_heater.md deleted file mode 100644 index b4a13e29..00000000 --- a/website/translated_docs/nl/entity_water_heater.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: Water Heater Entity -sidebar_label: Water Heater ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| -------------- | ------ | ------- | ------------------------------------------ | -| min_temp | float | 110°F | The minimum temperature that can be set. | -| max_temp | float | 140°F | The maximum temperature that can be set. | -| temperature | float | none | The current temperature in °C or °F. | -| operation_mode | string | none | The current operation mode. | -| operation_list | list | none | List of possible operation modes. | -| away_mode | string | none | The current status of away mode. (on, off) | - -The allowed operation modes are specified in the base component and implementations of the water_heater component cannot differ. - -Properties have to follow the units defined in the `unit_system`. - -## States - -| State | Description | -| ------------------- | ---------------------------------------------------------------- | -| `STATE_ECO` | Energy efficient mode, provides energy savings and fast heating. | -| `STATE_ELECTRIC` | Electric only mode, uses the most energy. | -| `STATE_PERFORMANCE` | High performance mode. | -| `STATE_HIGH_DEMAND` | Meet high demands when water heater is undersized. | -| `STATE_HEAT_PUMP` | Slowest to heat, but uses less energy. | -| `STATE_GAS` | Gas only mode, uses the most energy. | -| `STATE_OFF` | The water heater is off. | - -## Methods - -### `set_temperature` or `async_set_temperature` - -Sets the temperature the water heater should heat water to. - -### `set_operation_mode`or `async_set_operation_mode` - -Sets the operation mode of the water heater. Must be in the operation_list. - -### `turn_away_mode_on` or `async_turn_away_mode_on` - -Set the water heater to away mode. - -### `turn_away_mode_off` or `async_turn_away_mode_off` - -Set the water heater back to the previous operation mode. Turn off away mode. \ No newline at end of file diff --git a/website/translated_docs/nl/entity_weather.md b/website/translated_docs/nl/entity_weather.md deleted file mode 100644 index b92ccbe6..00000000 --- a/website/translated_docs/nl/entity_weather.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Weather Entity -sidebar_label: Weather ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------ | ------ | ------------ | ----------------------------------------------- | -| state | string | **Required** | The current weather condition. | -| temperature | float | **Required** | The current temperature in °C or °F. | -| pressure | float | `None` | The current air pressure in hPa or inHg. | -| humidity | float | `None` | The current humidity in %. | -| visibility | float | `None` | The current visibility in km or mi. | -| wind_speed | float | `None` | The current wind speed in km/h or mi/h. | -| wind_bearing | string | `None` | The current wind bearing, 1-3 letters. | -| forecast | array | `None` | Daily or Hourly forecast data. | -| attribution | string | `None` | The branding text required by the API provider. | - -Properties have to follow the units defined in the `unit_system`. - -### Forecast - -Forecast data should either be daily or hourly. - -| Name | Type | Default | Description | -| ----------- | ------ | ------------ | --------------------------------------- | -| datetime | string | **Required** | UTC Date time in RFC 3339 format. | -| temperature | float | **Required** | The higher temperature in °C or °F | -| condition | string | `None` | The weather condition at this point. | -| templow | float | `None` | The lower daily Temperature in °C or °F | - -### Recommended values for state and condition - -These weather conditions are included in our translation files and also show the corresponding icon. - -| Condition | Description | -| --------------- | --------------------------------- | -| clear-night | Clear night | -| cloudy | Many clouds | -| fog | Fog | -| lightning | Lightning/ thunderstorms | -| lightning-rainy | Lightning/ thunderstorms and rain | -| partlycloudy | A few clouds | -| pouring | Pouring rain | -| rainy | Rain | -| snowy | Snow | -| snowy-rainy | Snow and Rain | -| sunny | Sunshine | -| windy | Wind | -| windy-variant | Wind and clouds | - -This means that the `weather` platforms don't need to support languages. \ No newline at end of file diff --git a/website/translated_docs/nl/external_api_rest.md b/website/translated_docs/nl/external_api_rest.md deleted file mode 100644 index 965aae96..00000000 --- a/website/translated_docs/nl/external_api_rest.md +++ /dev/null @@ -1,530 +0,0 @@ ---- -title: "REST API" ---- - -Home Assistant provides a RESTful API on the same port as the web frontend. (default port is port 8123). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -- http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -- http://IP_ADDRESS:8123/api/ is a RESTful API. - -The API accepts and returns only JSON encoded objects. - -All API calls have to be accompanied by the header `Authorization: Bearer ABCDEFGH`, where `ABCDEFGH` is replaced by your token. You can obtain a token ("Long-Lived Access Token") by logging into the frontend using a web browser, and going to [your profile](https://www.home-assistant.io/docs/authentication/#your-account-profile) `http://IP_ADDRESS:8123/profile`. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```bash -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. - -```python -from requests import get - -url = 'http://localhost:8123/ENDPOINT' -headers = { - 'Authorization': 'Bearer ABCDEFGH', - 'content-type': 'application/json', -} - -response = get(url, headers=headers) -print(response.text) -``` - -Another option is to use the Restful Command component https://www.home-assistant.io/components/rest_command/ in a Home Assistant automation or script. - -```yaml -turn_light_on: - url: http://localhost:8123/api/states/light.study_light - method: POST - headers: - authorization: 'Bearer ABCDEFGH' - content-type: 'application/json' - payload: '{"state":"on"}' -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on one or more entities - comma separated. -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates the current state of an entity. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance. - - -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` \ No newline at end of file diff --git a/website/translated_docs/nl/external_api_rest_python.md b/website/translated_docs/nl/external_api_rest_python.md deleted file mode 100644 index 3d415b76..00000000 --- a/website/translated_docs/nl/external_api_rest_python.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: "REST API - Python bindings" ---- - -This API is deprecated and was removed since Home Assistant 0.77.0 - -More information can be found in this [blog post](../../../blog/2018/08/13/deprecating-remote-package.html). \ No newline at end of file diff --git a/website/translated_docs/nl/external_api_server_sent_events.md b/website/translated_docs/nl/external_api_server_sent_events.md deleted file mode 100644 index 676494c3..00000000 --- a/website/translated_docs/nl/external_api_server_sent_events.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: "Server-sent events" ---- - -The [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) feature is a one-way channel from your Home Assistant server to a client which is acting as a consumer. For a bi-directional streaming API, check out the [WebSocket API](external_api_websocket.md). - -The URI that is generating the data is `/api/stream`. - -A requirement on the client-side is existing support for the [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) interface. - -There are various ways to access the stream. If you have not set an `api_password` in the [`http`](https://www.home-assistant.io/components/http/) section of your `configuration.yaml` file then you use your modern browser to read the messages. A command-line option is `curl`: - -```bash -$ curl -X GET -H 'Authorization: Bearer ABCDEFGH' \ - -H "Content-Type: application/json" http://localhost:8123/api/stream -``` - -> Will no longer work with the new Authentication system. - -You can create a convenient view for this by creating an HTML file (`sse.html`) in the `www` folder of your Home Assistant configuration directory (`.homeassistant`). Paste this snippet into the file: - -```html - - - -

Getting Home Assistant server events

-
- - - -``` - -Visit to see the stream of events. - -## Examples - -A simple way to consume server-sent events is to use a command-line http client like [httpie](https://httpie.org/). Installation info is on the site (if you use Homebrew, it's `brew install httpie`). Once installed, run this snippet from your terminal: - -```bash -$ http --stream http://localhost:8123/api/stream 'Authorization:Bearer ABCDEFGH' content-type:application/json -``` - -### Website - -> Will no longer work with the new Authentication system. - -The [home-assistant-sse](https://github.com/fabaff/home-assistant-sse) repository contains a more advanced example. - -### Python - -If you want to test the server-sent events without creating a website, the Python module [`sseclient` ](https://pypi.python.org/pypi/sseclient/) can help. To install (assuming Python and pip3 are already installed): - -```bash -$ pip3 install sseclient -``` - -A simple script to consume SSE in Python looks like this: - -```python -from sseclient import SSEClient - -auth = {'Authorization': 'Bearer ABCDEFGH'} -messages = SSEClient('http://localhost:8123/api/stream', headers=auth) - -for msg in messages: - print(msg) -``` \ No newline at end of file diff --git a/website/translated_docs/nl/external_api_websocket.md b/website/translated_docs/nl/external_api_websocket.md deleted file mode 100644 index f194c309..00000000 --- a/website/translated_docs/nl/external_api_websocket.md +++ /dev/null @@ -1,434 +0,0 @@ ---- -title: "WebSocket API" ---- - -Home Assistant contains a WebSocket API. This API can be used to stream information from a Home Assistant instance to any client that implements WebSockets. Implementations in different languages: - -- [JavaScript](https://github.com/home-assistant/home-assistant-js-websocket) - powers the frontend -- [Python](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket-client.py) - CLI client using [`asyncws`](https://async-websockets.readthedocs.io/en/latest/) -- [JavaScript/HTML](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket.html) - WebSocket connection in your browser - -Connect your websocket implementation to `ws://localhost:8123/api/websocket`. You will need a valid access token. - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`websocket_api` component](https://www.home-assistant.io/components/websocket_api/) to your `configuration.yaml` file to use the WebSocket API. - -## Server states - -1. Client connects. -2. Authentication phase starts. - - Server sends `auth_required` message. - - Client sends `auth` message. - - If `auth` message correct: go to 3. - - Server sends `auth_invalid`. Go to 6. -3. Send `auth_ok` message -4. Authentication phase ends. -5. Command phase starts. - 1. Client can send commands. - 2. Server can send results of previous commands. -6. Client or server disconnects session. - -During the command phase, the client attaches a unique identifier to each message. The server will add this identifier to each message so that the client can link each message to its origin. - -## Message format - -Each API message is a JSON serialized object containing a `type` key. After the authentication phase messages also must contain an `id`, an integer that contains the number of interactions. - -Example of an auth message: - -```json -{ - "type": "auth", - "access_token": "ABCDEFGHIJKLMNOPQ" -} -``` - -```json -{ - "id": 5, - "type":"event", - "event":{ - "data":{}, - "event_type":"test_event", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -## Authentication phase - -When a client connects to the server, the server will test if the client is authenticated. Authentication will not be necessary if no api_password is set or if the user fulfills one of the other criteria for authentication (trusted network, password in url/header). - -If no authentication is needed, the authentication phase will complete and the server will send an `auth_ok` message. - -```json -{ - "type": "auth_ok" -} -``` - -If authentication is necessary, the server sends out `auth_required`. - -```json -{ - "type": "auth_required" -} -``` - -This means that the next message from the client should be an auth message. You can authorize with an access token. - -```json -{ - "type": "auth", - "access_token": "ABCDEFGH" -} -``` - -For now, we also support authentication with an API password (legacy auth). - -```json -{ - "type": "auth", - "api_password": "supersecret" -} -``` - -If the client supplies valid authentication, the authentication phase will complete by the server sending the `auth_ok` message: - -```json -{ - "type": "auth_ok" -} -``` - -If the data is incorrect, the server will reply with `auth_invalid` message and disconnect the session. - -```json -{ - "type": "auth_invalid", - "message": "Invalid password" -} -``` - -## Command phase - -During this phase the client can give commands to the server. The server will respond to each command with a `result` message indicating when the command is done and if it was successful. - -```json -{ - "id": 6, - "type": "result", - "success": true, - // Can contain extra result info - "result": null -} -``` - -## Subscribe to events - -The command `subscribe_events` will subscribe your client to the event bus. You can either listen to all events or to a specific event type. If you want to listen to multiple event types, you will have to send multiple `subscribe_events` commands. - -```json -{ - "id": 18, - "type": "subscribe_events", - // Optional - "event_type": "state_changed" -} -``` - -The server will respond with a result message to indicate that the subscription is active. - -```json -{ - "id": 18, - "type": "result", - "success": true, - "result": null -} -``` - -For each event that matches, the server will send a message of type `event`. The `id` in the message will point at the original `id` of the `listen_event` command. - -```json -{ - "id": 18, - "type":"event", - "event":{ - "data":{ - "entity_id":"light.bed_light", - "new_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:24.265390+00:00", - "state":"on", - "attributes":{ - "rgb_color":[ - 254, - 208, - 0 - ], - "color_temp":380, - "supported_features":147, - "xy_color":[ - 0.5, - 0.5 - ], - "brightness":180, - "white_value":200, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:24.265390+00:00" - }, - "old_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:10.466994+00:00", - "state":"off", - "attributes":{ - "supported_features":147, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:10.466994+00:00" - } - }, - "event_type":"state_changed", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -### Unsubscribing from events - -You can unsubscribe from previously created subscription events. Pass the id of the original subscription command as value to the subscription field. - -```json -{ - "id": 19, - "type": "unsubscribe_events", - "subscription": 18 -} -``` - -The server will respond with a result message to indicate that unsubscribing was successful. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": null -} -``` - -## Calling a service - -This will call a service in Home Assistant. Right now there is no return value. The client can listen to `state_changed` events if it is interested in changed entities as a result of a service call. - -```json -{ - "id": 24, - "type": "call_service", - "domain": "light", - "service": "turn_on", - // Optional - "service_data": { - "entity_id": "light.kitchen" - } -} -``` - -The server will indicate with a message indicating that the service is done executing. - -```json -{ - "id": 24, - "type": "result", - "success": true, - "result": null -} -``` - -## Fetching states - -This will get a dump of all the current states in Home Assistant. - -```json -{ - "id": 19, - "type": "get_states" -} -``` - -The server will respond with a result message containing the states. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -## Fetching config - -This will get a dump of the current config in Home Assistant. - -```json -{ - "id": 19, - "type": "get_config" -} -``` - -The server will respond with a result message containing the config. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -## Fetching services - -This will get a dump of the current services in Home Assistant. - -```json -{ - "id": 19, - "type": "get_services" -} -``` - -The server will respond with a result message containing the services. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -## Fetching panels - -This will get a dump of the current registered panels in Home Assistant. - -```json -{ - "id": 19, - "type": "get_panels" -} -``` - -The server will respond with a result message containing the current registered panels. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -## Fetching camera thumbnails - -*Introduced in Home Assistant 0.69.* - -Return a b64 encoded thumbnail of a camera entity. - -```json -{ - "id": 19, - "type": "camera_thumbnail" -} -``` - -The server will respond with a result message containing the thumbnail. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Fetching media player thumbnails - -*Introduced in Home Assistant 0.69.* - -Fetch a base64 encoded thumbnail picture for a media player. - -```json -{ - "id": 19, - "type": "media_player_thumbnail", - "entity_id": "media_player.living_room" -} -``` - -The server will respond with the image encoded via base64. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Pings and Pongs - -The API supports receiving a ping from the client and returning a pong. This serves as a heartbeat to ensure the connection is still alive: - -```json -{ - "id": 19, - "type": "ping" -} -``` - -The server must send a pong back as quickly as possible, if the connection is still active: - -```json -{ - "id": 19, - "type": "pong" -} -``` - -## Error handling - -If an error occurs, the `success` key in the `result` message will be set to `false`. It will contain an `error` key containing an object with two keys: `code` and `message`. - -| Code | Description | -| ---- | ------------------------------------------------------------------------- | -| 1 | A non-increasing identifier has been supplied. | -| 2 | Received message is not in expected format (voluptuous validation error). | -| 3 | Requested item cannot be found | - -```json -{ - "id": 12, - "type":"result", - "success": false, - "error": { - "code": 2, - "message": "Message incorrectly formatted: expected str for dictionary value @ data['event_type']. Got 100" - } -} -``` \ No newline at end of file diff --git a/website/translated_docs/nl/frontend_add_card.md b/website/translated_docs/nl/frontend_add_card.md deleted file mode 100644 index 5958da27..00000000 --- a/website/translated_docs/nl/frontend_add_card.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Adding state card" ---- - -The main interface of Home Assistant is a list of the current entities and their states. For each entity in the system, a state card will be rendered. State cards will show an icon, the name of the entity, when the state has last changed and the current state or a control to interact with it. - -![Cards in the frontend](/img/en/frontend/frontend-cards1.png) - -The different card types can be found [here](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary). - -Sensors, when not grouped, are shown as so-called badges on top of the state cards. - -![Badges in the frontend](/img/en/frontend/frontend-badges.png) - -The different badges are located in the file [`/src/components/entity/ha-state-label-badge.js`](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/components/entity/ha-state-label-badge.js). - -Adding a custom card type can be done with a few simple steps. For this example we will add a new state card for the domain `camera`: - -1. Add `'camera'` to the array `DOMAINS_WITH_CARD` in the file [/common/const.ts](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/common/const.ts). -2. Create the files `state-card-camera.js` in the folder [/state-summary/](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary). -3. Add `import './state-card-camera.js';` to [state-card-content.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/state-summary/state-card-content.js). \ No newline at end of file diff --git a/website/translated_docs/nl/frontend_add_more_info.md b/website/translated_docs/nl/frontend_add_more_info.md deleted file mode 100644 index 56519938..00000000 --- a/website/translated_docs/nl/frontend_add_more_info.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: "Adding more info dialogs" ---- - -Whenever the user taps or clicks on one of the cards, a more info dialog will show. The header of this dialog will be the state card, followed by the history of this entity for the last 24 hours. Below this the more info component is rendered for that entity. The more info component can show more information or allow more ways of control. - -![The more info dialog for a light allows the user to control the color and the brightness.](/img/en/frontend/frontend-more-info-light.png) - -The instructions to add a more info dialog are very similar to adding a new card type. This example will add a new more info component for the domain `camera`: - -1. Add `'camera'` to the array `DOMAINS_WITH_MORE_INFO` in the file [/common/const.ts](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/common/const.ts). -2. Create the files `more-info-camera.js` in the folder [/dialogs/more-info/controls](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/dialogs/more-info/controls). -3. Add `import './more-info-camera.js';` to [/dialogs/more-info/controls/more-info-content.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/dialogs/more-info/controls/more-info-content.js) \ No newline at end of file diff --git a/website/translated_docs/no-NO/app_integration_notifications.md b/website/translated_docs/no-NO/app_integration_notifications.md deleted file mode 100644 index a4861554..00000000 --- a/website/translated_docs/no-NO/app_integration_notifications.md +++ /dev/null @@ -1,235 +0,0 @@ ---- -title: "Push Notifications" ---- - -The `mobile_app` component has a notify platform built in that allows for a generic way to send push notifications to your users without requiring installation of a external custom component. - -## Enabling push notifications - -To enable the notify platform for your application, you must set two keys in the `app_data` object during the initial registration or later update of an existing registration. - -| Key | Type | Description | -| ------------ | ------ | -------------------------------------------------------------------------------------------------------------------------- | -| `push_token` | string | A push notification token unique to your users device. For example, this could be a APNS token or a FCM Instance ID/token. | -| `push_url` | string | The URL on your server that push notifications will be HTTP POSTed to. | - -You should advise the user to restart Home Assistant after you set these keys in order for them to see the notify target. It will have the format `notify.mobile_app_`. - -## Deploying a server component - -The notify platform doesn't concern itself with how to notify your users. It simply forwards a notification to your external server where you should actually handle the request. This approach allows you to maintain full control over your push notification infrastructure. - -See the next section of this document for an example server implementation of a push notification forwarder that uses Firebase Cloud Functions and Firebase Cloud Messaging. - -Your server should accept a HTTP POST payload like this: - -```json -{ - "message": "Hello World", - "title": "Test message sent via mobile_app.notify", - "push_token": "my-secure-token", - "registration_info": { - "app_id": "io.home-assistant.iOS", - "app_version": "1.0.0", - "os_version": "12.2" - }, - "data": { - "key": "value" - } -} -``` - -It should respond with a 201 status code assuming the notification was queued for delivery successfully. - -### Errors - -If an error occurs you should return a description of what went wrong with a status code *other than* 201 or 429. An error response must be a JSON object and can contain one of the following keys: - -| Key | Type | Description | -| -------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `errorMessage` | string | If provided, it will be appended to a preset error message. For example, if `errorMessage` is "Could not communicate with Apple" it will be output in the log like "Internal server error, please try again later: Could not communicate with Apple" | -| `message` | string | If provided, it will be output directly to the logs at the warning log level. | - -No matter what key you use, you should try to be as descriptive as possible about what went wrong and, if possible, how the user can fix it. - -### Rate limits - -The notify platform also supports exposing rate limits to users. Home Assistant suggests you implement a conservative rate limit to keep your costs low and also so that users don't overload themselves with too many notifications. For reference, Home Assistant Companion has a maximum sendable notifications per 24 hours of 150 notifications. The rate limit resets for all users at midnight, UTC. You of course are free to use whatever configuration for your own rate limiting. - -If you choose to implement rate limiting, your successful server response should look like the following: - -```json -{ - "rateLimits": { - "successful": 1, - "errors": 5, - "maximum": 150, - "resetsAt": "2019-04-08T00:00:00.000Z" - } -} -``` - -| Key | Type | Description | -| ------------ | ----------------- | ------------------------------------------------------------------------------------------------ | -| `successful` | integer | The number of successful push notifications the user has sent during the rate limit period. | -| `errors` | integer | The number of failed push notifications the user has sent during the rate limit period. | -| `maximum` | integer | The maximum number of push notifications the user can send during the users rate limit period. | -| `resetsAt` | ISO8601 timestamp | The timestamp that the users rate limit period expires at. Must be provided in the UTC timezone. | - -The rate limits will be output to the log at the warning log level after every notification is successfully sent. Home Assistant will also output the exact time remaining until the rate limit period resets. - -Once the user hits their maximum amount of notifications sent in the rate limit period, you should start responding with a 429 status code until the rate limit period expires. The response object can optionally contain a key, `message` which will be output to the Home Assistant log instead of the standard error message. - -The notify platform does not itself implement any kind of rate limit protections. Users will be able to keep sending you notifications, so you should reject them with a 429 status code as early in your logic as possible. - -## Example server implementation - -The below code is a Firebase Cloud Function that forwards notifications to Firebase Cloud Messaging. To deploy this, you should create a new Firestore database named `rateLimits`. Then, you can deploy the following code. Also, ensure that you have properly configured your project with the correct authentication keys for APNS and FCM. - -```javascript -'use strict'; - -const functions = require('firebase-functions'); -const admin = require('firebase-admin'); -admin.initializeApp(); - -var db = admin.firestore(); - -const MAX_NOTIFICATIONS_PER_DAY = 150; - -exports.sendPushNotification = functions.https.onRequest(async (req, res) => { - console.log('Received payload', req.body); - var today = getToday(); - var token = req.body.push_token; - var ref = db.collection('rateLimits').doc(today).collection('tokens').doc(token); - - var payload = { - notification: { - body: req.body.message, - }, - token: token, - }; - - if(req.body.title) { - payload.notification.title = req.body.title; - } - - if(req.body.data) { - if(req.body.data.android) { - payload.android = req.body.data.android; - } - if(req.body.data.apns) { - payload.apns = req.body.data.apns; - } - if(req.body.data.data) { - payload.data = req.body.data.data; - } - if(req.body.data.webpush) { - payload.webpush = req.body.data.webpush; - } - } - - console.log('Notification payload', JSON.stringify(payload)); - - var docExists = false; - var docData = { - deliveredCount: 0, - errorCount: 0, - totalCount: 0, - }; - - try { - let currentDoc = await ref.get(); - docExists = currentDoc.exists; - if(currentDoc.exists) { - docData = currentDoc.data(); - } - } catch(err) { - console.error('Error getting document!', err); - return handleError(res, 'getDoc', err); - } - - if(docData.deliveredCount > MAX_NOTIFICATIONS_PER_DAY) { - return res.status(429).send({ - errorType: 'RateLimited', - message: 'The given target has reached the maximum number of notifications allowed per day. Please try again later.', - target: token, - rateLimits: getRateLimitsObject(docData), - }); - } - - docData.totalCount = docData.totalCount + 1; - - var messageId; - try { - messageId = await admin.messaging().send(payload); - docData.deliveredCount = docData.deliveredCount + 1; - } catch(err) { - docData.errorCount = docData.errorCount + 1; - await setRateLimitDoc(ref, docExists, docData, res); - return handleError(res, 'sendNotification', err); - } - - console.log('Successfully sent message:', messageId); - - await setRateLimitDoc(ref, docExists, docData, res); - - return res.status(201).send({ - messageId: messageId, - sentPayload: payload, - target: token, - rateLimits: getRateLimitsObject(docData), - }); - -}); - -async function setRateLimitDoc(ref, docExists, docData, res) { - try { - if(docExists) { - console.log('Updating existing doc!'); - await ref.update(docData); - } else { - console.log('Creating new doc!'); - await ref.set(docData); - } - } catch(err) { - if(docExists) { - console.error('Error updating document!', err); - } else { - console.error('Error creating document!', err); - } - return handleError(res, 'setDocument', err); - } - return true; -} - -function handleError(res, step, incomingError) { - if (!incomingError) return null; - console.error('InternalError during', step, incomingError); - return res.status(500).send({ - errorType: 'InternalError', - errorStep: step, - message: incomingError.message, - }); -} - -function getToday() { - var today = new Date(); - var dd = String(today.getDate()).padStart(2, '0'); - var mm = String(today.getMonth() + 1).padStart(2, '0'); - var yyyy = today.getFullYear(); - return yyyy + mm + dd; -} - -function getRateLimitsObject(doc) { - var d = new Date(); - return { - successful: (doc.deliveredCount || 0), - errors: (doc.errorCount || 0), - total: (doc.totalCount || 0), - maximum: MAX_NOTIFICATIONS_PER_DAY, - remaining: (MAX_NOTIFICATIONS_PER_DAY - doc.deliveredCount), - resetsAt: new Date(d.getFullYear(), d.getMonth(), d.getDate()+1) - }; -} -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/app_integration_sensors.md b/website/translated_docs/no-NO/app_integration_sensors.md deleted file mode 100644 index 08a30ce9..00000000 --- a/website/translated_docs/no-NO/app_integration_sensors.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "Sensors" ---- - -The `mobile_app` component supports exposing custom sensors that can be managed entirely via your app. - -## Registering a sensor - -All sensors must be registered before they can get updated. You can only register one sensor at a time, unlike updating sensors. - -To register a sensor, make a request to the webhook like this: - -```json -{ - "data": { - "attributes": { - "foo": "bar" - }, - "device_class": "battery", - "icon": "mdi:battery", - "name": "Battery State", - "state": "12345", - "type": "sensor", - "unique_id": "battery_state", - "unit_of_measurement": "%" - }, - "type": "register_sensor" -} -``` - -The valid keys are: - -| Key | Type | Required | Description | -| --------------------- | ----------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| attributes | object | No | Attributes to attach to the sensor | -| device_class | string | No | One of the valid device classes. [Binary Sensor Classes](https://www.home-assistant.io/components/binary_sensor/#device-class), [Sensor Classes](https://www.home-assistant.io/components/sensor/#device-class) | -| icon | Material Design Icon (string) | No | Must be prefixed `mdi:`. If not provided, default value is `mdi:cellphone` | -| name | string | Yes | The name of the sensor | -| state | bool, float, int, string | Yes | The state of the sensor | -| type | string | Yes | The type of the sensor. Must be one of `binary_sensor` or `sensor` | -| unique_id | string | Yes | A identifier unique to this installation of your app. You'll need this later. Usually best when its a safe version of the sensor name | -| unit_of_measurement | string | No | The unit of measurement for the sensor | - -Sensors will appear as soon as they are registered. - -## Updating a sensor - -Once a sensor has been registered, you need to update it. This is very similar to registering it, but you can update all your sensors at the same time. - -For example, to update the sensor we registered above, you would send this: - -```json -{ - "data": [ - { - "attributes": { - "hello": "world" - }, - "icon": "mdi:battery", - "state": 123, - "type": "sensor", - "unique_id": "battery_state" - } - ], - "type": "update_sensor_states" -} -``` - -Only some of the keys are allowed during updates: - -| Key | Type | Required | Description | -| ---------- | ----------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- | -| attributes | object | No | Attributes to attach to the sensor | -| icon | Material Design Icon (string) | No | Must be prefixed `mdi:` | -| state | bool, float, int, string | Yes | The state of the sensor | -| type | string | Yes | The type of the sensor. Must be one of `binary_sensor` or `sensor` | -| unique_id | string | Yes | A identifier unique to this installation of your app. You'll need this later. Usually best when its a safe version of the sensor name | \ No newline at end of file diff --git a/website/translated_docs/no-NO/app_integration_setup.md b/website/translated_docs/no-NO/app_integration_setup.md deleted file mode 100644 index efd3a03b..00000000 --- a/website/translated_docs/no-NO/app_integration_setup.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: "Connecting to an instance" ---- - -When a user first opens the app, they will need to connect to their local instance to authenticate and register the device. - -## Authenticating the user - -The local instance can be discovered if Home Assistant has the [zeroconf component](https://www.home-assistant.io/components/zeroconf) configured by searching for `_home-assistant._tcp.local.`. If not configured, the user will need to be asked for the local address of their instance. - -When the address of the instance is known, the app will ask the user to authenticate via [OAuth2 with Home Assistant](auth_api.md). Home Assistant uses IndieAuth, which means that to be able to redirect to a url that triggers your app, you need to take some extra steps. Make sure to read the last paragraph of the "Clients" section thoroughly. - -## Registering the device - -*This requires Home Assistant 0.90 or later.* - -Home Assistant has a `mobile_app` component that allows applications to register themselves and interact with the instance. This is a generic component to handle most common mobile application tasks. This component is extendable with custom interactions if your app needs more types of interactions than are offered by this component. - -Once you have tokens to authenticate as a user, it's time to register the app with the mobile app component in Home Assistant. - -### Getting Ready - -First, you must ensure that the `mobile_app` component is loaded. There are two ways to do this: - -- You can publish a Zeroconf/Bonjour record `_hass-mobile-app._tcp.local.` to trigger the automatic load of the `mobile_app` component. You should wait at least 60 seconds after publishing the record before continuing. -- You can ask the user to add `mobile_app` to their configuration.yaml and restart Home Assistant. If the user already has `default_config` in their configuration, then `mobile_app` will have been already loaded. - -You can confirm the `mobile_app` component has been loaded by checking the `components` array of the [`/api/config` REST API call](external_api_rest.md#get-api-config). If you continue to device registration and receive a 404 status code, then it most likely hasn't been loaded yet. - -### Registering the device - -To register the device, make an authenticated POST request to `/api/mobile_app/registrations`. [More info on making authenticated requests.](auth_api.md#making-authenticated-requests) - -Example payload to send to the registration endpoint: - -```json -{ - "app_id": "awesome_home", - "app_name": "Awesome Home", - "app_version": "1.2.0", - "device_name": "Robbies iPhone", - "manufacturer": "Apple, Inc.", - "model": "iPhone X", - "os_version": "iOS 10.12", - "supports_encryption": true, - "app_data": { - "push_notification_key": "abcdef", - } -} -``` - -| Key | Required | Type | Description | -| --------------------- | -------- | ------ | --------------------------------------------------------------------------------------------------- | -| `app_id` | V | string | A unique identifier for this app. | -| `app_name` | V | string | Name of the mobile app. | -| `app_version` | V | string | Version of the mobile app. | -| `device_name` | V | string | Name of the device running the app. | -| `manufacturer` | V | string | The manufacturer of the device running the app. | -| `model` | V | string | The model of the device running the app. | -| `os_version` | V | string | The OS version of the device running the app. | -| `supports_encryption` | V | bool | If the app supports encryption. See also the [encryption section](#encryption). | -| `app_data` | | Dict | App data can be used if the app has a supporting component that extends `mobile_app` functionality. | - -When you get a 200 response, the mobile app is registered with Home Assistant. The response is a JSON document and will contain the URLs on how to interact with the Home Assistant instance. You should permanently store this information. - -```json -{ - "cloudhook_url": "https://hooks.nabu.casa/randomlongstring123", - "remote_ui_url": "https://randomlongstring123.ui.nabu.casa", - "secret": "qwerty", - "webhook_id": "abcdefgh" -} -``` - -| Key | Type | Description | -| --------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `cloudhook_url` | string | The cloudhook URL provided by Home Assistant Cloud. Only will be provided if user is actively subscribed to Nabu Casa. | -| `remote_ui_url` | string | The remote UI URL provided by Home Assistant Cloud. Only will be provided if user is actively subscribed to Nabu Casa. | -| `secret` | string | The secret to use for encrypted communication. Will only be included if encryption is supported by both the app and the Home Assistant instance. [More info](app_integration_sending_data.md#implementing-encryption). | -| `webhook_id` | string | The webhook ID that can be used to send data back. | \ No newline at end of file diff --git a/website/translated_docs/no-NO/app_integration_webview.md b/website/translated_docs/no-NO/app_integration_webview.md deleted file mode 100644 index 82bc53d8..00000000 --- a/website/translated_docs/no-NO/app_integration_webview.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Authenticated Webview" ---- - -Your application already asked the user to authenticate. This means that your app should not ask the user to authenticate again when they open the Home Assistant UI. - -To make this possible, the Home Assistant UI supports [external authentication](frontend_external_auth). This allows your app to provide hooks so that the frontend will ask your app for access tokens. - -Note that this feature requires a direct connection to the instance. \ No newline at end of file diff --git a/website/translated_docs/no-NO/architecture_components.md b/website/translated_docs/no-NO/architecture_components.md deleted file mode 100644 index a1031012..00000000 --- a/website/translated_docs/no-NO/architecture_components.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Components Architecture" -sidebar_label: "Components" ---- - -Home Assistant can be extended with **components**. Each component is responsible for a specific domain within Home Assistant. Components can listen for or trigger events, offer services, and maintain states. Components are written in Python and can do all the goodness that Python has to offer. Out of the box, Home Assistant offers a bunch of [built-in components](https://www.home-assistant.io/components/). - -Diagram showing interaction between components and the Home Assistant core. - -There are two types of components within Home Assistant: components that interact with an Internet of Things domain, and components that respond to events that happen within Home Assistant. Read on to learn about each type! - -## Components that interact with an Internet-of-Things domain - -These components track devices within a specific domain and consist of a core part and platform-specific logic. These components make their information available via the State Machine and the Event Bus. The components also register services in the Service Registry to expose control of the devices. - -For example, the built-in [`switch` component](https://www.home-assistant.io/components/switch/) is responsible for interaction with different types of switches. A platform provides support for a particular kind or brand of device. For example, a switch could use a WeMo or Orvibo platform and a light component might interact with the Hue or LIFX platform. - -If you want to add support for a new platform, check out the [add new platform section](creating_platform_index.md). - -## Components that respond to events that happen within Home Assistant - -These components provide small pieces of home automation logic or involve services that do common tasks within your house. - -For example, the [`device_sun_light_trigger` component](https://www.home-assistant.io/components/device_sun_light_trigger/) tracks the state of devices and the sun to make sure that the lights are turned on when it gets dark and people are home. The component uses logic like this: - -```text -In the event that device 'Paulus Nexus 5' changes to the 'Home' state: - If the sun has set and the lights are not on: - Turn on the lights -``` - -```text -In the event that the combined state of all tracked devices changes to 'Not Home': - If the lights are on: - Turn off the lights -``` - -```text -In the event of the sun setting: - If the lights are off and the combined state of all tracked device equals 'Home': - Turn on the lights -``` - -## The full picture - -When we put all the different pieces of Home Assistant together, it's a close match for the initial home automation overview sketch. The smart home AI has not been implemented yet, so it's not included in this picture. - -![Overview of the full Home Assistant architecture with a couple of loaded components and platforms](/img/en/architecture/ha_full_architecture.png) - -The platform logic for components uses third-party Python libraries to communicate with the devices. Through this, we can leverage some of the best libraries in the Python community. \ No newline at end of file diff --git a/website/translated_docs/no-NO/architecture_entities.md b/website/translated_docs/no-NO/architecture_entities.md deleted file mode 100644 index 82535365..00000000 --- a/website/translated_docs/no-NO/architecture_entities.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Entity Architecture" -sidebar_label: Entity ---- - -![Architecture overview of Hass.io](/img/en/architecture/entities_architecture.png) - -## Configuration - -Configuration is provided by the [configuration.yaml file](configuration_yaml_index.md) or by a [Config Entry](config_entries_index.md). - -## Component - -Examples of components: `light`, `switch`. - -The component is responsible for defining the Abstract Entity Class and services to control the entities. - -## Entity Component - -The Entity Component is responsible for: - -- Distributing the configuration to the platforms -- Forward config entries and discoveries -- Collect entities for service calls -- Optionally maintain a group of all entities - -## Entity Platform - -The Entity Platform manages all entities for the platform and polls them for updates if necessary. - -When adding entities, the Entity Platform will query the Entity Registry to make sure that the entities to be added have the correct entity IDs. - -## Entity Registry - -The [Entity Registry](entity_registry_index.md) will track entities and allows users to store extra settings for an entity. - -## Platform - -Examples of platforms: `light.hue`, `switch.wemo`. - -Platform uses configuration to query the external device/service and add entities to the entity platform. \ No newline at end of file diff --git a/website/translated_docs/no-NO/architecture_hassio.md b/website/translated_docs/no-NO/architecture_hassio.md deleted file mode 100644 index df33383a..00000000 --- a/website/translated_docs/no-NO/architecture_hassio.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Hass.io Architecture" -sidebar_label: Hass.io ---- - -![Architecture overview of Hass.io](/img/en/architecture/hassio.png) - -## Host Control (HC) - -This is a daemon running on the host machine that allows the supervisor to control certain aspects of the host OS: - -- Power cycle (restart, turn off) -- Manage network settings -- Local updates - -## Host - -Our pre-build images are based on [HassOS](https://github.com/home-assistant/hassos) which is based on [BuildRoot](https://buildroot.org/). Any Linux machine can be turned into a Hass.io host by running [the installer](https://www.home-assistant.io/hassio/installation/#alternative-install-on-generic-linux-server). - -## Supervisor - -The supervisor offers an API to manage the host and running the Docker containers. - -## Configuration panel - -The configuration panel lives inside the supervisor but is accessible via the Home Assistant user interface. The configuration panel allows the user to manage the installation. \ No newline at end of file diff --git a/website/translated_docs/no-NO/architecture_index.md b/website/translated_docs/no-NO/architecture_index.md deleted file mode 100644 index 550a818d..00000000 --- a/website/translated_docs/no-NO/architecture_index.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: "Architecture" -sidebar_label: "Introduction" ---- - -Before we dive into the Home Assistant architecture, let's get a clear overview of the home automation landscape as a whole. This way, we can show how the different parts of Home Assistant fit into the picture. - -For more information about each part in this overview, [check out our blog](https://www.home-assistant.io/blog/2014/12/26/home-control-home-automation-and-the-smart-home/). Here's the tl;dr version of the blog: - -- Home Control is responsible for collecting information and controlling devices. -- Home Automation triggers commands based on user configurations. -- Smart Home triggers commands based on previous behavior. - -![Home Automation landscape](/img/en/architecture/home_automation_landscape.svg) - -The Home Assistant core is responsible for Home Control. Home Assistant contains four parts which make this possible: - -- **Event Bus**: facilitates the firing and listening of events -- the beating heart of Home Assistant. -- **State Machine**: keeps track of the states of things and fires a `state_changed` event when a state has been changed. -- **Service Registry**: listens on the event bus for `call_service` events and allows other code to register services. -- **Timer**: sends a `time_changed` event every 1 second on the event bus. - -![Overview of the Home Assistant core architecture](/img/en/architecture/ha_architecture.svg) \ No newline at end of file diff --git a/website/translated_docs/no-NO/area_registry_index.md b/website/translated_docs/no-NO/area_registry_index.md deleted file mode 100644 index faf0d208..00000000 --- a/website/translated_docs/no-NO/area_registry_index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Area Registry -sidebar_label: Introduction ---- - -The area registry is a registry where Home Assistant keeps track of areas. An area represents a physical location for Home Assistant. It can be used to place devices in different areas. - -| Attribute | Description | -| --------- | ----------------------------------------------- | -| id | Unique ID of area (generated by Home Assistant) | -| name | Name of this area | \ No newline at end of file diff --git a/website/translated_docs/no-NO/asyncio_101.md b/website/translated_docs/no-NO/asyncio_101.md deleted file mode 100644 index 3ffc7dd7..00000000 --- a/website/translated_docs/no-NO/asyncio_101.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Asyncio 101" ---- - -If you are not familiar yet with asyncio, please watch the below video. It's a great introduction by [Robert Smallshire](https://github.com/rob-smallshire) in how and why asyncio works the way it does. - -
- -
diff --git a/website/translated_docs/no-NO/asyncio_categorizing_functions.md b/website/translated_docs/no-NO/asyncio_categorizing_functions.md deleted file mode 100644 index 71e8206d..00000000 --- a/website/translated_docs/no-NO/asyncio_categorizing_functions.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: "Categorizing Functions" ---- - -A piece of work within Home Assistant is represented by a function that will be invoked. It will either run inside our event loop or inside our thread pool, depending on if it is async safe. - -Home Assistant uses the convention that all functions that must be run from within the event loop are prefixed with `async_`. - -## The coroutine function - -Coroutines are special functions based on Python’s generators syntax which allows them to suspend execution while waiting on a result. - -Invoking a coroutine function will return a Generator object back, but will not actually begin execution. This object will execute the task when it is either yielded from (from within another coroutine) or it is scheduled on the event loop. - -To declare a function a coroutine, import the coroutine annotation from the asyncio package and annotate your function. - -```python -async def async_look_my_coroutine(target): - result = await entity.async_turn_on() - if result: - print("hello {}".format(target)) - -hass.loop.create_task(async_look_my_coroutine("world")) -``` - -In this example, we schedule the coroutine by calling `hass.loop.create_task`. This will add the coroutine to the queue of tasks to be run. When the event loop is running `async_look_my_coroutine` it will suspend the task when `await entity.async_turn_on()` is called. At that point a new task will be scheduled to execute `entity.async_turn_on()`. When that job has been executed, `async_look_my_coroutine` will resume. - -## The callback function - -This is a normal function that is considered safe to be run from within the event loop. A callback is unable to suspend itself and thus cannot do any I/O or call a coroutine. A callback is capable of scheduling a new task but it will not be able to wait for the results. - -To declare a function as a callback, import the callback annotation from the core package and annotate your function. - -A common use case for a callback in Home Assistant is as a listener for an event or a service call. It can process the incoming information and then schedule the right calls to be made. Example from the automation component. - -```python -from homeassistant.core import callback - -@callback -def async_trigger_service_handler(service_call): - """Handle automation trigger service calls.""" - vars = service_call.data.get(ATTR_VARIABLES) - for entity in component.async_extract_from_service(service_call): - hass.loop.create_task(entity.async_trigger(vars, True)) -``` - -In this example, `entity.async_trigger` is a coroutine function. Invoking the coroutine function will return a coroutine task. The passed in parameters will be used when the task gets executed. - -To execute the task we have to schedule it for execution on the event loop. This is done by calling `hass.loop.create_task`. - -### Why even have callbacks? - -You might wonder, if a coroutine can do everything a callback can do, why even have a callback. The reason is performance and better state consistency of the core API objects. - -When coroutine A waits for coroutine B, it will suspend itself and schedule a new task to run B. This means that the event loop is now running A, B and then A again. If B is a callback, A will never have to suspend itself and thus the event loop is just running A. The consistency implication is that other events queued to run on the event loop continue to wait until callbacks complete, but will be interleaved when yielding to another coroutine. - -## Event loop and thread safe - -These are functions that are safe to run both in a thread and inside the event loop. These functions are usually performing a computation or transform data in memory. Anything that does I/O does not fall under this category. Many standard library functions fall in this category. For example generating the sum of a set of numbers using sum or merging two dictionaries. - -There is no special annotation to mark functions as part of this category and care should be taken when using these functions from inside the event loop. When in doubt, look at their implementation. - -## Other functions - -These are all the functions that did not fit in the previous categories. These functions are either thread-safe or not considered safe to be run within the event loop. These are functions that use sleep, or perform I/O. - -There is no special annotation necessary to be considered part of this category. \ No newline at end of file diff --git a/website/translated_docs/no-NO/asyncio_index.md b/website/translated_docs/no-NO/asyncio_index.md deleted file mode 100644 index 6dd2ecaa..00000000 --- a/website/translated_docs/no-NO/asyncio_index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "Asynchronous Programming" -sidebar_label: Introduction ---- - -On September 29, 2016 we released [Home Assistant 0.29](https://www.home-assistant.io/blog/2016/09/29/async-sleepiq-emoncms-stocks/) as part of our bi-weekly release schedule. This release introduced a complete overhaul of the core spearheaded by [Ben Bangert](https://github.com/bbangert/). - -The old core was set up like a “traditional” threaded application. Each resource that was not thread safe (ie. the state of entities) would be protected by a lock. This caused a lot of waiting and potential inconsistency because a task could now end up waiting halfway through its job until some resource got freed. - -Our new core is based on Python’s built-in **asyncio** module. Instead of having all threads have access to the core API objects, access is now limited to a special thread called the *event loop*. All components will now schedule themselves as a task to be executed by the event loop. This gives us the guarantee that only a single task is executed at the same time, meaning we no longer need any locks. - -The only problem with running everything inside the event loop is when a task does blocking I/O; something most third-party Python libraries do. For example, while requesting new information from a device, the core will stop running until we get a response from the device. To handle this, a task is able to suspend itself until the response is available, after which it will be enqueued in the event loop to process the result. - -For a task to be able to suspend itself, all code that it calls must support this capability. In practice, this would mean that each device integration will need a full rewrite of the library that offers the integration! As this is something that cannot be achieved, ever, a 100% backwards compatible API has been added so that no platform will require updating. - -The backwards compatible API schedules a task in a different thread and blocks that thread until the task has been processed by the event loop. \ No newline at end of file diff --git a/website/translated_docs/no-NO/asyncio_working_with_async.md b/website/translated_docs/no-NO/asyncio_working_with_async.md deleted file mode 100644 index 6f56876c..00000000 --- a/website/translated_docs/no-NO/asyncio_working_with_async.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: "Working with Async" ---- - -Although we have a backwards compatible API, using the async core directly will be a lot faster. Most core components have already been rewritten to leverage the async core. This includes the EntityComponent helper (foundation of light, switch, etc), scripts, groups and automation. - -## Interacting with the core - -[All methods in the Home Assistant core](https://dev-docs.home-assistant.io/en/master/api/core.html) are implemented in two flavors: an async version and a version to be called from other threads. The versions for other are merely wrappers that call the async version in a threadsafe manner. - -So if you are making calls to the core (the hass object) from within a callback or coroutine, use the methods that start with async_. If you need to call an async_ function that is a coroutine, your task must also be a coroutine. - -## Implementing an async component - -To make a component async, implement an async_setup. - -```python -def setup(hass, config): - # Setup your component outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup(hass, config): - # Setup your component inside of the event loop. -``` - -## Implementing an async platform - -For platforms we support async setup. Instead of setup_platform you need to have a coroutine async_setup_platform. - -```python -setup_platform(hass, config, add_entities, discovery_info=None): - # Setup your platform outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup_platform(hass, config, async_add_entities, - discovery_info=None): - # Setup your platform inside of the event loop -``` - -The only difference with the original parameters is that the `add_entities` function has been replaced by the async friendly callback `async_add_entities`. - -## Implementing an async entity - -You can make your entity async friendly by converting your update method to be async. This requires the dependency of your entities to also be async friendly! - -```python -class MyEntity(Entity): - def update(self): - """Retrieve latest state.""" - self._state = fetch_state() -``` - -Will turn into: - -```python -class MyEntity(Entity): - async def async_update(self): - """Retrieve latest state.""" - self._state = await async_fetch_state() -``` - -Make sure that all properties defined on your entity do not result in I/O being done. All data has to be fetched inside the update method and cached on the entity. This is because these properties are read from within the event loop and thus doing I/O will result in the core of Home Assistant waiting until your I/O is done. - -## Calling async functions from threads - -Sometimes it will happen that you’re in a thread and you want to call a function that is only available as async. Home Assistant includes a few async helper utilities to help with this. - -In the following example, `say_hello` will schedule `async_say_hello` and block till the function has run and get the result back. - -```python -import asyncio - -def say_hello(hass, target): - return asyncio.run_coroutine_threadsafe( - async_say_hello(hass, target), hass.loop).result() - -async def async_say_hello(hass, target): - return "Hello {}!".format(target) -``` - -## Calling sync functions from async - -If you are running inside an async context, it might sometimes be necessary to call a sync function. Do this like this: - -```python -# hub.update() is a sync function. -result = await hass.async_add_executor_job(hub.update) -``` - -## Starting independent task from async - -If you want to spawn a task that will not block the current async context, you can choose to create it as a task on the event loop. It will then be executed in parallel. - -```python -hass.async_create_task(async_say_hello(hass, target)) -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/auth_api.md b/website/translated_docs/no-NO/auth_api.md deleted file mode 100644 index 0fa664fa..00000000 --- a/website/translated_docs/no-NO/auth_api.md +++ /dev/null @@ -1,245 +0,0 @@ ---- -title: "Authentication API" -sidebar_label: API ---- - -This page will describe the steps required for your application to authorize against and integrate with Home Assistant instances. [See a demo](https://hass-auth-demo.glitch.me) powered by our helper lib [home-assistant-js-websocket](https://github.com/home-assistant/home-assistant-js-websocket). - -Each user has their own instance of Home Assistant which gives each user control over their own data. However, we also wanted to make it easy for third party developers to create applications that allow users to integrate with Home Assistant. To achieve this, we have adopted the [OAuth 2 specification](https://tools.ietf.org/html/rfc6749) combined with the [OAuth 2 IndieAuth extension](https://indieauth.spec.indieweb.org/) for generating clients. - -## Clients - -Before you can ask the user to authorize their instance with your application, you will need a client. In traditional OAuth2, the server needs to generate a client before a user can authorize. However, as each server belongs to a user, we've adopted a slightly different approach from [IndieAuth](https://indieauth.spec.indieweb.org/#client-identifier). - -The client ID you need to use is the website of your application. The redirect url has to be of the same host and port as the client ID. For example: - -- client id: `https://www.my-application.io` -- redirect uri: `https://www.my-application.io/hass/auth_callback` - -If you require a different redirect url (ie, if building a native app), you can add an HTML tag to the content of the website of your application (the client ID) with an approved redirect url. For example, add this to your site to whitelist redirect uri `hass://auth`: - -```html - -``` - -Home Assistant will scan the first 10kB of a website for link tags. - -## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) - -> All example URLs here are shown with extra spaces and new lines for display purposes only. - -The authorize url should contain `client_id` and `redirect_uri` as query parameters. - - http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2F%3Fauth_callback%3D1 - - -Optionally you can also include a `state` parameter, this will be added to the redirect uri. The state is perfect to store the instance url that you are authenticating with. Example: - - http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2Fauth_callback& - state=http%3A%2F%2Fhassio.local%3A8123 - - -The user will navigate to this link and be presented with instructions to log in and authorize your application. Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code and state as part of the query parameters. Example: - - https://hass-auth-demo.glitch.me/auth_callback - code=12345& - state=http%3A%2F%2Fhassio.local%3A8123 - - -This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section). - -## Token - -The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. In thee case of refresh token, the token endpoint is also capable of revoking a token. - -All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`. - -### Authorization code - -> All requests to the token endpoint need to contain the exact same client ID as was used to redirect the user to the authorize endpoint. - -Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is: - - grant_type=authorization_code& - code=12345& - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me - - -The return response will be an access and refresh token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "refresh_token": "IJKLMNOPQRST", - "token_type": "Bearer" -} -``` - -The access token is a short lived token that can be used to access the API. The refresh token can be used to fetch new access tokens. The `expires_in` value is seconds that the access token is valid. - -An HTTP status code of 400 will be returned if an invalid request has been issued. The HTTP status code will be 403 if a token is requested for an inactive user. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Refresh token - -Once you have retrieved a refresh token via the grant type `authorization_code`, you can use it to fetch new access tokens. The request body is: - - grant_type=refresh_token& - refresh_token=IJKLMNOPQRST& - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me - - -The return response will be an access token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "token_type": "Bearer" -} -``` - -An HTTP status code of 400 will be returned if an invalid request has been issued. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Revoking a refresh token - -> client_id is not need for revoke refresh token - -The token endpoint is also capable of revoking a refresh token. Revoking a refresh token will immediately revoke the refresh token and all access tokens that it has ever granted. To revoke a refresh token, make the following request: - - token=IJKLMNOPQRST& - action=revoke - - -The request will always respond with an empty body and HTTP status 200, regardless if the request was successful. - -## Long-lived access token - -A long-lived access token is usually used for 3rd party API calls and webhook-ish integrations. To generate a long-lived access token, an active websocket connection has to be established. - -Send websocket command `auth/long_lived_access_token` will create a long-lived access token for current user. Access token will not be saved in Home Assistant. User need to record the token in secure place. - -```json -{ - "id": 11, - "type": "auth/long_lived_access_token", - "client_name": "GPS Logger", - "client_icon": null, - "lifespan": 365 -} -``` - -Result will be a long-lived access token: - -```json -{ - "id": 11, - "type": "result", - "success": true, - "result": "ABCDEFGH" -} -``` - -Additionally, a long-lived access token can be created using the UI tool located at the bottom of the user's Home Assistant profile page. - -## Making authenticated requests - -Once you have an access token, you can make authenticated requests to the Home Assistant APIs. - -For the websocket connection, pass the access token in the [authentication message](https://developers.home-assistant.io/docs/en/external_api_websocket.html#authentication-phase). - -For HTTP requests, pass the token type and access token as the authorization header: - - Authorization: Bearer ABCDEFGH - - -### Example: cURL - -```shell -curl -X GET \ - https://your.awesome.home/api/error/all \ - -H 'Authorization: Bearer ABCDEFGH' -``` - -### Example: Python - -```python -import requests - -url = "https://your.awesome.home/api/error/all" -headers = { - 'Authorization': "Bearer ABCDEFGH", -} -response = requests.request('GET', url, headers=headers) - -print(response.text) -``` - -### Example: NodeJS - -```JavaScript -fetch('https://your.awesome.home/api/error/all', { - headers: { Authorization: 'Bearer ABCDEFGH' } -}).then(function (response) { - if (!response.ok) { - return Promise.reject(response); - } - return response.text(); -}).then(function (body ) { - console.log(body); -}); -``` - -If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and so the user is no longer logged in. You should clear the user's data and ask the user to authorize again. - -## Signed paths - -Sometimes you want a user to make a GET request to Home Assistant to download data. In this case the normal auth system won't do, as we can't link the user to an API with the auth header attached to it. In that case, a signed path can help. - -A signed path is a normal path on our server, like `/api/states`, but with an attached secure authentication signature. The user is able to navigate to this path and will be authorised as the access token that created the signed path. Signed paths can be created via the websocket connection and are meant to be shortlived. The default expiration is 30 seconds. - -To get a signed path, send the following command: - -```js -{ - "type": "auth/sign_path", - "path": "/api/states", - // optional, expiration time in seconds. Defaults to 30 seconds - "expires": 20 -} -``` - -The response will contain the signed path: - -```js -{ - "path": "/api/states?authSig=ABCDEFGH" -} -``` - -Some things to note about a signed path: - -- If the refresh token is deleted, the signed url is no longer valid. -- If the user is deleted, the signed url is no longer valid (because the refresh token will be deleted). -- If Home Assistant is restarted, the signed url is no longer valid. -- Access is only validated when the request is received. If a response takes longer than the expiration time (ie, downloading a large file), the download will continue after the expiration date has passed. \ No newline at end of file diff --git a/website/translated_docs/no-NO/auth_auth_module.md b/website/translated_docs/no-NO/auth_auth_module.md deleted file mode 100644 index e0e000a7..00000000 --- a/website/translated_docs/no-NO/auth_auth_module.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: "Multi-factor Authentication Modules" ---- - -Multi-factor Authentication Modules are used in conjunction with [Authentication Provider](auth_auth_provider.html) to provide a fully configurable authentication framework. Each MFA module may provide one multi-factor authentication function. User can enable multiple mfa modules, but can only select one module in login process. - -## Defining an mfa auth module - -> We currently only support built-in mfa auth modules. Support for custom auth modules might arrive in the future. - -Multi-factor Auth modules are defined in `homeassistant/auth/mfa_modules/.py`. The auth module will need to provide an implementation of the `MultiFactorAuthModule` class. - -For an example of a fully implemented auth module, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/mfa_modules/insecure_example.py). - -Multi-factor Auth modules shall extend the following methods of `MultiFactorAuthModule` class. - -| method | Required | Description | -| ---------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -| `@property def input_schema(self)` | Yes | Return a schema defined the user input form. | -| `async def async_setup_flow(self, user_id)` | Yes | Return a SetupFlow to handle the setup workflow. | -| `async def async_setup_user(self, user_id, setup_data)` | Yes | Set up user for use this auth module. | -| `async def async_depose_user(self, user_id)` | Yes | Remove user information from this auth module. | -| `async def async_is_user_setup(self, user_id)` | Yes | Return whether user is set up. | -| `async def async_validate(self, user_id, user_input)` | Yes | Given a user_id and user input, return validation result. | -| `async def async_initialize_login_mfa_step(self, user_id)` | No | Will be called once before display the mfa step of login flow. This is not initialization for the MFA module but the mfa step in login flow. | - -## Setup Flow - -Before user can use a multi-factor auth module, it has to be enabled or set up. All available modules will be listed in user profile page, user can enable the module he/she wants to use. A setup data entry flow will guide user finish the necessary steps. - -Each MFA module need to implement a setup flow handler extends from `mfa_modules.SetupFlow` (if only one simple setup step need, `SetupFlow` can be used as well). For example for Google Authenticator (TOTP, Time-based One Time Password) module, the flow will need to be: - -- Generate a secret and store it on instance of setup flow -- Return `async_show_form` with a QR code in the description (injected as base64 via `description_placeholders`) -- User scans code and enters a code to verify it scanned correctly and clock in synced -- TOTP module saved the secret along with user_id, module is enabled for user - -## Workflow - -![Multi Factor Authentication Workflow](/img/en/auth/mfa_workflow.png) - - - -## Configuration example - -```yaml -# configuration.xml -homeassistant: - auth_providers: - - type: homeassistant - - type: legacy_api_password - auth_mfa_modules: - - type: totp - - type: insecure_example - users: [{'user_id': 'a_32_bytes_length_user_id', 'pin': '123456'}] -``` - -In this example, user will first select from `homeassistant` or `legacy_api_password` auth provider. For `homeassistant` auth provider, user will first input username/password, if that user enabled both `totp` and `insecure_example`, then user need select one auth module, then input Google Authenticator code or input pin code base on the selection. - -> insecure_example is only for demo purpose, please do not use it in production. - -## Validation session - -Not like auth provider, auth module use session to manage the validation. After auth provider validated, mfa module will create a validation session, include an experiation time and user_id from auth provider validate result. Mutli-factor auth module will not only verify the user input, but also verify the session is not expired. The validation session data is stored in your configuration directory. \ No newline at end of file diff --git a/website/translated_docs/no-NO/auth_auth_provider.md b/website/translated_docs/no-NO/auth_auth_provider.md deleted file mode 100644 index b652973d..00000000 --- a/website/translated_docs/no-NO/auth_auth_provider.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Authentication Providers" ---- - -Authentication providers confirm the identity of users. The user proofs their identity by going through the login flow for an auth provider. The auth provider defines the login flow and can ask the user all information this needs. This will commonly be username and password but could also include a 2FA token or other challenges. - -Once an authentication provider has confirmed the identity of a user, it will pass that on to Home Assistant in the form of a Credentials object. - -## Defining an auth provider - -> We currently only support built-in auth providers. Support for custom auth providers might arrive in the future. - -Auth providers are defined in `homeassistant/auth/providers/.py`. The auth provider module will need to provide an implementation of the `AuthProvider` class and `LoginFlow` class, it is what asks user for information and validates it base on `data_entry_flow`. - -For an example of a fully implemented auth provider, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/providers/insecure_example.py). - -Auth providers shall extend the following methods of `AuthProvider` class. - -| method | Required | Description | -| ---------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| async def async_login_flow(self) | Yes | Return an instance of the login flow for a user to identify itself. | -| async def async_get_or_create_credentials(self, flow_result) | Yes | Given the result of a login flow, return a credentials object. This can either be an existing one or a new one. | -| async def async_user_meta_for_credentials(credentials) | No | Callback called Home Assistant is going to create a user from a Credentials object. Can be used to populate extra fields for the user. | - -Auth providers shall extend the following methods of `LoginFlow` class. - -| method | Required | Description | -| -------------------------------------------------- | -------- | ------------------------------------------------ | -| async def async_step_init(self, user_input=None) | Yes | Handle the login form, see more detail in below. | - -## async_step_init of LoginFlow - -> We may change this inteface in near future. - -`LoginFlow` extends `data_entry_flow.FlowHandler`. The first step of data entry flow is hard coded as `init`, so each flow has to implement `async_step_init` method. The pattern of `async_step_init` likes following pseudo-code: - -```python -async def async_step_init(self, user_input=None): - return self.async_show_form(step_id='init', data_schema='some schema to construct ui form') if user_input is None - return self.async_show_form(step_id='init', errors) if user_input is invalid - return await self.async_finish(username) if user_input is valid -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/auth_index.md b/website/translated_docs/no-NO/auth_index.md deleted file mode 100644 index 695e6c7d..00000000 --- a/website/translated_docs/no-NO/auth_index.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Authentication" -sidebar_label: Introduction ---- - -Home Assistant has a built-in authentication system allowing different users to interact with Home Assistant. The authentication system consist of various parts. - -![Overview of how the different parts interact](/img/en/auth/architecture.png) - -## Authentication providers - -An authentication provider is used for users to authenticate themselves. It's up to the authentication provider to choose the method of authentication and the backend to use. By default we enable the built-in Home Assistant authentication provider which stores the users securely inside your configuration directory. - -The authentication providers that Home Assistant will use are specified inside `configuration.yaml`. It is possible to have multiple instances of the same authentication provider active. In that case, each will be identified by a unique identifier. Authentication providers of the same type will not share credentials. - -## Credentials - -Credentials store the authentication of a user with a specific authentication provider. It is produced when a user successfully authenticates. It will allow the system to find the user in our system. If the user does not exist, a new user will be created. This user will not be activated but will require approval by the owner. - -It is possible for a user to have multiple credentials linked to it. However, it can only have a single credential per specific authentication provider. - -## Users - -Each person is a user in the system. To log in as a specific user, authenticate with any of the authentication providers that are linked to this user. When a user logs in, it will get a refresh and an access token to make requests to Home Assistant. - -### Owner - -The user that is created during onboarding will be marked as "owner". The owner is able to manage other users and will always have access to all permissions. - -## Groups - -Users are a member of one or more groups. Group membership is how a user is granted permissions. - -## Permission Policy - -This is the permission policy that describes to which resources a group has access. For more information about permissions and policies, see [Permissions](auth_permissions.md). - -## Access and refresh tokens - -Applications that want to access Home Assistant will ask the user to start an authorization flow. The flow results in an authorization code when a user successfully authorizes the application with Home Assistant. This code can be used to retrieve an access and a refresh token. The access token will have a limited lifetime while refresh tokens will remain valid until a user deletes it. - -The access token is used to access the Home Assistant APIs. The refresh token is used to retrieve a new valid access token. - -### Refresh token types - -There are three different types of refresh tokens: - -- *Normal*: These are the tokens that are generated when a user authorizes an application. The application will hold on to these tokens on behalf of the user. -- *Long-lived Access Token*: These are refresh tokens that back a long lived access token. They are created internally and never exposed to the user. -- *System*: These tokens are limited to be generated and used by system users like Hass.io. They are never exposed to the user. \ No newline at end of file diff --git a/website/translated_docs/no-NO/auth_permissions.md b/website/translated_docs/no-NO/auth_permissions.md deleted file mode 100644 index 9aed470e..00000000 --- a/website/translated_docs/no-NO/auth_permissions.md +++ /dev/null @@ -1,266 +0,0 @@ ---- -title: "Permissions" ---- - -> This is an experimental feature that is not enabled or enforced yet - -Permissions limit the things a user has access to or can control. Permissions are attached to groups, of which a user can be a member. The combined permissions of all groups a user is a member of decides what a user can and cannot see or control. - -Permissions do not apply to the user that is flagged as "owner". This user will always have access to everything. - -## General permission structure - -Policies are dictionaries that at the root level consist of different categories of permissions. In the current implementation this is limited to just entities. - -```python -{ - "entities": … -} -``` - -Each category can further split into subcategories that describe parts of that category. - -```python -{ - "entities": { - "domains": …, - "entity_ids": … - } -} -``` - -If a category is omitted, the user will not have permission to that category. - -When defining a policy, any dictionary value at any place can be replaced with `True` or `None`. `True` means that permission is granted and `None` means use default, which is deny access. - -## Entities - -Entity permissions can be set on a per entity and per domain basis using the subcategories `entity_ids`, `device_ids`, `area_ids` and `domains`. You can either grant all access by setting the value to `True`, or you can specify each entity individually using the "read", "control", "edit" permissions. - -The system will return the first matching result, based on the order: `entity_ids`, `device_ids`, `area_ids`, `domains`, `all`. - -```json -{ - "entities": { - "domains": { - "switch": true - }, - "entity_ids": { - "light.kitchen": { - "read": true, - "control": true - } - } - } -} -``` - -## Merging policies - -If a user is a member of multiple groups, the groups permission policies will be combined into a single policy at runtime. When merging policies, we will look at each level of the dictionary and compare the values for each source using the following methodology: - -1. If any of the values is `True`, the merged value becomes `True`. -2. If any value is a dictionary, the merged value becomes a dictionary created by recursively checking each value using this methodology. -3. If all values are `None`, the merged value becomes `None`. - -Let's look at an example: - -```python -{ - "entities": { - "entity_ids": { - "light.kitchen": True - } - } -} -``` - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -Once merged becomes - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -## Checking permissions - -We currently have two different permission checks: can the user do the read/control/edit operation on an entity, and is the user an admin and thus allowed to change this configuration setting. - -Certain APIs will always be accessible to all users, but might offer a limited scope based on the permissions, like rendering a template. - -### Checking permissions - -To check a permission, you will need to have access to the user object. Once you have the user object, checking the permission is easy. - -```python -from homeassistant.exceptions import Unauthorized -from homeasistant.permissions.const import ( - POLICY_READ, POLICY_CONTROL, POLICY_EDIT -) - -# Raise error if user is not an admin -if not user.is_admin: - raise Unauthorized() - - -# Raise error if user does not have access to control an entity -# Available policies: POLICY_READ, POLICY_CONTROL, POLICY_EDIT -if not user.permissions.check_entity(entity_id, POLICY_CONTROL): - raise Unauthorized() -``` - -### The context object - -All service calls, fired events and states in Home Assistant have a context object. This object allows us to attribute changes to events and services. These context objects also contain a user id, which is used for checking the permissions. - -It's crucial for permission checking that actions taken on behalf of the user are done with a context containing the user ID. If you are in a service handler, you should re-use the incoming context `call.context`. If you are inside a WebSocket API or Rest API endpoint, you should create a context with the correct user: - -```python -from homeassistant.core import Context - -await hass.services.async_call('homeassistant', 'stop', context=Context( - user_id=user.id -), blocking=True) -``` - -### If a permission check fails - -When you detect an anauthorized action, you should raise the `homeassistant.exceptions.Unauthorized` exception. This exception will cancel the current action and notifies the user that their action is unauthorized. - -The `Unauthorized` exception has various parameters, to identify the permission check that failed. All fields are optional. - -| # Not all actions have an ID (like adding config entry) | # We then use this fallback to know what category was unauth - -| Parameter | Description | -| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| context | The context of the current call. | -| user_id | The user ID that we tried to operate on. | -| entity_id | The entity ID that we tried to operate on. | -| config_entry_id | The config entry ID that we tried to operate on. | -| perm_category | The permission category that we tested. Only necessary if we don't have an object ID that the user tried to operate on (like when we create a config entry). | -| permission | The permission that we tested, ie `POLICY_READ`. | - -### Securing a service call handler - -Service calls allow a user to control entities or with the integration as a whole. A service call uses the attached context to see which user invoked the command. Because context is used, it is important that you also pass the call context to all service calls. - -All services that are registered via the entity component (`component.async_register_entity_service()`) will automatically have their permissions checked. - -#### Checking entity permissions - -Your service call handler will need to check the permissions for each entity that it will act on. - -```python -from homeassistant.exceptions import Unauthorized, UnknownUser -from homeassistant.auth.permissions.const import POLICY_CONTROL - -async def handle_entity_service(call): - """Handle a service call.""" - entity_ids = call.data['entity_id'] - - for entity_id in entity_ids: - if call.context.user_id: - user = await hass.auth.async_get_user(call.context.user_id) - - if user is None: - raise UnknownUser( - context=call.context, - entity_id=entity_id, - permission=POLICY_CONTROL, - ) - - if not user.permissions.check_entity(entity_id, POLICY_CONTROL): - raise Unauthorized( - context=call.context, - entity_id=entity_id, - permission=POLICY_CONTROL, - ) - - # Do action on entity - - -async def async_setup(hass, config): - hass.services.async_register(DOMAIN, 'my_service', handle_entity_service) - return True -``` - -#### Checking admin permission - -Starting Home Assistant 0.90, there is a special decorator to help protect services that require admin access. - -```python -# New in Home Assistant 0.90 -async def handle_admin_service(call): - """Handle a service call.""" - # Do admin action - - -async def async_setup(hass, config): - hass.helpers.service.async_register_admin_service( - DOMAIN, 'my_service', handle_admin_service, vol.Schema({}) - ) - return True -``` - -### Securing a REST API endpoint - -```python -from homeassistant.core import Context -from homeassistant.components.http.view import HomeAssistantView -from homeassistant.exceptions import Unauthorized - - -class MyView(HomeAssistantView): - """View to handle Status requests.""" - - url = '/api/my-component/my-api' - name = 'api:my-component:my-api' - - async def post(self, request): - """Notify that the API is running.""" - hass = request.app['hass'] - user = request['hass_user'] - - if not user.is_admin: - raise Unauthorized() - - hass.bus.async_fire('my-component-api-running', context=Context( - user_id=user.id - )) - - return self.json_message("Done.") -``` - -### Securing a Websocket API endpoint - -Verifying permissions in a Websocket API endpoint can be done by accessing the user via `connection.user`. If you need to check admin access, you can use the built-in `@require_admin` decorator. - -```python -from homeassistant.compnents import websocket_api - - -async def async_setup(hass, config): - hass.components.websocket_api.async_register_command(websocket_create) - return True - - -@websocket_api.require_admin -@websocket_api.async_response -@websocket_api.websocket_command({ - vol.Required('type'): 'my-component/my-action', -}) -async def websocket_create(hass, connection, msg): - """Create a user.""" - # Do action -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/config_entries_config_flow_handler.md b/website/translated_docs/no-NO/config_entries_config_flow_handler.md deleted file mode 100644 index 6fe750d0..00000000 --- a/website/translated_docs/no-NO/config_entries_config_flow_handler.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Integration Configuration -sidebar_label: Configuration ---- - -> This option is currently only available for built-in components. - -Integrations can be set up via the user interface by adding support for config entries. Config entries uses the [data flow entry framework](data_entry_flow_index.md) to allow users to create entries. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like Hass.io). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -To register your config flow handler with Home Assistant, register it with the config entries `HANDLERS` registry: - -```python -from homeassistant import config_entries - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(config_entries.ConfigFlow): -``` - -All config flow handlers will also need to add their domain name to the `FLOWS` constant in `homeassistant/config_entries.py`. - -## Discovering your config flow - -Home Assistant has a discovery integration that scans the network for available devices and services and will trigger the config flow of the appropriate integration. Discovery is limited to UPnP and zeroconf/mDNS. - -To have your integration be discovered, you will have to extend the [NetDisco library](https://github.com/home-assistant/netdisco) to be able to find your device. This is done by adding a new discoverable. [See the repository for examples of existing discoverable.](https://github.com/home-assistant/netdisco/tree/master/netdisco/discoverables) - -Once done, you will have to update the discovery integration to make it aware which discovery maps to which integration, by updating [this list](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery/__init__.py#L55). - -Finally, you will have to add support to your config flow to be triggered from discovery. This is done by adding a new discovery step. Make sure that your discovery step does not automatically create an entry. All discovered config flows are required to have a confirmation from the user. - -Once discovered, the user will be notified that they can continue the flow from the config panel. - -```python -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` - -When the translations are merged into Home Assistant, they will be automatically uploaded to [Lokalise](https://lokalise.co/) where the translation team will help to translate them in other languages. [More info on translating Home Assistant.](internationalization_translation.md) - -## Triggering other config flows - -If you are writing an integration that discovers other integrations, you will want to trigger their config flows so the user can set them up. Do this by passing a source parameter and optional user input when initializing the config entry: - -```python -await hass.config_entries.flow.async_init( - 'hue', data=discovery_info, - context={'source': config_entries.SOURCE_DISCOVERY}) -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/config_entries_index.md b/website/translated_docs/no-NO/config_entries_index.md deleted file mode 100644 index 2416509c..00000000 --- a/website/translated_docs/no-NO/config_entries_index.md +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: Config Entries -sidebar_label: Introduction ---- - -Config Entries are configuration data that are persistently stored by Home Assistant. A config entry is created by a user via the UI. The UI flow is powered by a [config flow handler](config_entries_config_flow_handler.md) as defined by the component. Config entries can also have an extra [options flow handler](config_entries_options_flow_handler.md), also defined by the component. - -## Lifecycle - -| State | Description | -| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| not loaded | The config entry has not been loaded. This is the initial state when a config entry is created or when Home Assistant is restarted. | -| loaded | The config entry has been loaded. | -| setup error | An error occurred when trying to set up the config entry. | -| setup retry | A dependency of the config entry was not ready yet. Home Assistant will automatically retry loading this config entry in the future. Time between attempts will automatically increase. | -| migration error | The config entry had to be migrated to a newer version, but the migration failed. | -| failed unload | The config entry was attempted to be unloaded, but this was either not supported or it raised an exception. | -G - - - - - not loaded - - -not loaded - - - loaded - - -loaded - - - not loaded->loaded - - - - - - - setup error - - -setup error - - - not loaded->setup error - - - - - - - setup retry - - -setup retry - - - not loaded->setup retry - - - - - - - migration error - - -migration error - - - not loaded->migration error - - - - - - - loaded->not loaded - - - - - - - failed unload - - -failed unload - - - loaded->failed unload - - - - - - - setup error->not loaded - - - - - - - setup retry->not loaded - - - - - - - -## Setting up an entry - -During startup, Home Assistant first calls the [normal component setup](https://developers.home-assistant.io/docs/en/creating_component_index.html), and then call the method `async_setup_entry(hass, entry)` for each entry. If a new Config Entry is created at runtime, Home Assistant will also call `async_setup_entry(hass, entry)` ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L119)). - -#### For platforms - -If a component includes platforms, it will need to forward the Config Entry to the platform. This can be done by calling the forward function on the config entry manager ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/bridge.py#L81)): - -```python -# Use `hass.async_add_job` to avoid a circular dependency between the platform and the component -hass.async_add_job(hass.config_entries.async_forward_entry_setup(config_entry, 'light')) -``` - -For a platform to support config entries, it will need to add a setup entry method ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/light/hue.py#L60)): - -```python -async def async_setup_entry(hass, config_entry, async_add_devices): -``` - -## Unloading entries - -Components can optionally support unloading a config entry. When unloading an entry, the component needs to clean up all entities, unsubscribe any event listener and close all connections. To implement this, add `async_unload_entry(hass, entry)` to your component ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L136)). - -For each platform that you forwarded the config entry to, you will need to forward the unloading too. - -```python -await self.hass.config_entries.async_forward_entry_unload(self.config_entry, 'light') -``` - -If you need to clean up resources used by an entity in a platform, have the entity implement the [`async_will_remove_from_hass`](entity_index.md#async_will_remove_from_hass) method. - -## Removal of entries - -If a component needs to clean up code when an entry is removed, it can define a removal method: - -```python -async def async_remove_entry(hass, entry) -> None: - """Handle removal of an entry.""" -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/creating_component_index.md b/website/translated_docs/no-NO/creating_component_index.md deleted file mode 100644 index 9f02858f..00000000 --- a/website/translated_docs/no-NO/creating_component_index.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "Creating a Minimal Component" -sidebar_label: "Minimal Component" ---- - -Alright, you learned about the [manifest](creating_integration_manifest.md), so it's time to write your first code for your integration. AWESOME. Don't worry, we've tried hard to keep it as easy as possible. - -More extensive examples of integrations are available from [our example repository](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/). - -## The code - -Each component needs to have 2 basic parts: it needs to define a `DOMAIN` constant that contains the domain of the integration. The second part is that it needs to define a setup method that returns a boolean if the set up was successful. So let's take a look at how this looks: - -```python -DOMAIN = 'hello_state' - -def setup(hass, config): - hass.states.set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -And if you prefer an async component: - -```python -DOMAIN = 'hello_state' - -async def async_setup(hass, config): - hass.states.async_set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -That's it! If you load this, you will see a new state in the state machine. - -To load this, add `hello_state:` to your `configuration.yaml` file and create a file `/custom_components/hello_state/__init__.py` with one of the two codeblocks above to test it locally. \ No newline at end of file diff --git a/website/translated_docs/no-NO/creating_integration_file_structure.md b/website/translated_docs/no-NO/creating_integration_file_structure.md deleted file mode 100644 index 3a535d07..00000000 --- a/website/translated_docs/no-NO/creating_integration_file_structure.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Integration File Structure" -sidebar_label: "File Structure" ---- - -Each integration is stored inside a directory named after the integration domain. The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. So all files for this integration are in the folder `mobile_app/`. - -The bare minimum content of this folder looks like this: - -- `manifest.json`: The manifest file describes the integration and its dependencies. [More info](creating_integration_manifest.md) -- `__init__.py`: The component file. If the integration only offers a platform, you can keep this file limited to a docstring introducing the integration `"""The Mobile App integration."""`. - -## Integrating devices - `light.py`, `switch.py` etc - -If your integration is going to integrate one or more devices, you will need to do this by creating a platform that interacts with an entity integration. For example, if you want to represent a light device inside Home Assistant, you will create `light.py`, which will contain a light platform for the light integration. - -- More info on [available entity integrations](entity_index.md). -- More info on [creating platforms](creating_platform_index.md). - -## Integrating services - `services.yaml` - -If your integration is going to register services, it will need to provide a description of the available services. The description is stored in `services.yaml`. [More information about `services.yaml`.](dev_101_services.md) - -## Where Home Assistant looks for integrations - -Home Assistant will look for an integration when it sees the domain referenced in the config file (i.e. `mobile_app:`) or if it is a dependency of another integration. Home Assistant will look at the following locations: - -- `/custom_components/` -- `homeassistant/components/` (built-in integrations) - -You can override a built-in integration by having an integration with the same domain in your `config/custom_components` folder. Note that overriding built-in components is not recommended as you will no longer get updates. It is recommended to pick a unique name. \ No newline at end of file diff --git a/website/translated_docs/no-NO/creating_integration_manifest.md b/website/translated_docs/no-NO/creating_integration_manifest.md deleted file mode 100644 index 7c76a6d7..00000000 --- a/website/translated_docs/no-NO/creating_integration_manifest.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "Integration Manifest" -sidebar_label: "Manifest" ---- - -Since 0.92.0, every integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, except for custom components. - -```json -{ - "domain": "hue", - "name": "Philips Hue", - "documentation": "https://www.home-assistant.io/components/hue", - "dependencies": ["mqtt"], - "codeowners": ["@balloob"], - "requirements": ["aiohue==1.9.1"] -} -``` - -Or a minimal example that you can copy into your project: - -```json -{ - "domain": "your_domain_name", - "name": "Your Integration", - "documentation": "https://www.example.com", - "dependencies": [], - "codeowners": [], - "requirements": [] -} -``` - -## Domain - -The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. - -## Name - -The name of the integration. - -## Documentation - -The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/` - -## Dependencies - -Dependencies are other Home Assistant integrations that you want Home Assistant to set up successfully prior to the integration being loaded. This can be necessary in case you want to offer functionality from that other integration, like using webhooks or an MQTT connection. - -## Code Owners - -GitHub usernames or team names of people that are responsible for this integration. You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included. - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you running in a virtual environment. This will make sure that all requirements are present at startup. If steps fail, like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is an array of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v3.2.0: `["pychromecast==3.2.0"]`. - -> Because of how Home Assistant installs requirements on demand, actual Python imports of your requirements should be done inside functions instead of at the root level of your Python files. - -### Custom requirements during development & testing - -During the development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using `pychromecast` as an example: - -```bash -pip install pychromecast==3.2.0 --target ~/.homeassistant/deps -hass --skip-pip -``` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is specified in `requirements`. - -If you need to make changes to a requirement to support your component, it's also possible to install a development version of the requirement using `pip install -e`: - -```bash -git clone https://github.com/balloob/pychromecast.git -pip install -e ./pychromecast -hass --skip-pip -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/creating_platform_code_review.md b/website/translated_docs/no-NO/creating_platform_code_review.md deleted file mode 100644 index a7609f74..00000000 --- a/website/translated_docs/no-NO/creating_platform_code_review.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: "Checklist for creating a platform" -sidebar_label: Platform Checklist ---- - -A checklist of things to do when you're adding a new platform. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - -1. Follow our [Style guidelines](development_guidelines.md) -2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - - Only add new constants to `const.py` if they are widely used. Otherwise keep them on platform level - - Use `CONF_MONITORED_CONDITIONS` instead of `CONF_MONITORED_VARIABLES` - -### 1. Requirements - -1. Requirements have been added to [`manifest.json`](creating_integration_manifest.md). The `REQUIREMENTS` constant is deprecated. -2. Requirement version should be pinned: `"requirements": ['phue==0.8.1']` -3. We no longer want requirements hosted on GitHub. Please upload to PyPi. -4. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Dependencies - -1. If you depend on a component for the connection, add it to your dependencies in [`manifest.json`](creating_integration_manifest.md): `"dependencies": ['nest']`. The `DEPENDENCIES` constant is deprecated. - -### 3. Configuration - -1. Voluptuous schema present for [configuration validation](development_validation.md) -2. Voluptuous schema extends schema from component - (e.g., `hue.light.PLATFORM_SCHEMA` extends `light.PLATFORM_SCHEMA`) -3. Default parameters specified in voluptuous schema, not in `setup_platform(...)` -4. Your `PLATFORM_SCHEMA` should use as many generic config keys as possible from `homeassistant.const` -5. Never depend on users adding things to `customize` to configure behavior inside your platform. - -```python -import voluptuous as vol - -from homeassistant.const import CONF_FILENAME, CONF_HOST -from homeassistant.components.light import PLATFORM_SCHEMA -import homeassistant.helpers.config_validation as cv - -CONF_ALLOW_UNREACHABLE = 'allow_unreachable' -DEFAULT_UNREACHABLE = False - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_ALLOW_UNREACHABLE, - default=DEFAULT_UNREACHABLE): cv.boolean, - vol.Optional(CONF_FILENAME): cv.string, -}) -``` - -### 4. Setup Platform - -1. Verify that the passed in configuration (user/pass/host etc.) works. -2. Group your calls to `add_devices` if possible. -3. If the platform adds extra services, the format should be `.`. So if your integration's domain is "awesome_sauce" and you are making a light platform, you would register services under the `awesome_sauce` domain. Make sure that your services [verify permissions](auth_permissions.md#checking-permissions). - -### 5. Entity - -1. Extend the entity from the integration you're building a platform for. - - ```python - from homeassistant.components.light import Light - - class HueLight(Light): - ... - ``` - -2. Avoid passing in `hass` as a parameter to the entity. When the entity has been added to Home Assistant, `hass` will be set on the entity when the entity is added to Home Assistant. This means you can access `hass` as `self.hass` inside the entity. - -3. Do not call `update()` in constructor, use `add_entities(devices, True)` instead. -4. Do not do any I/O inside properties. Cache values inside `update()` instead. -5. When dealing with time, state and/or attributes should not contain relative time since something happened. Instead, it should store UTC timestamps. -6. Leverage the [entity lifecycle callbacks](entity_index.md#lifecycle-hooks) to attach event listeners or clean up connections. - -### 6. Communication with devices/services - -1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - - ```python - # bad - status = requests.get(url('/status')) - - # good - from phue import Bridge - bridge = Bridge(...) - status = bridge.status() - ``` - - [Tutorial on publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) \ No newline at end of file diff --git a/website/translated_docs/no-NO/creating_platform_example_light.md b/website/translated_docs/no-NO/creating_platform_example_light.md deleted file mode 100644 index 2eb9bdbd..00000000 --- a/website/translated_docs/no-NO/creating_platform_example_light.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: "" ---- - -[This page has moved.](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_light) - - diff --git a/website/translated_docs/no-NO/creating_platform_example_sensor.md b/website/translated_docs/no-NO/creating_platform_example_sensor.md deleted file mode 100644 index 97d1683d..00000000 --- a/website/translated_docs/no-NO/creating_platform_example_sensor.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: "" ---- - -[This page has moved.](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_sensor) - - diff --git a/website/translated_docs/no-NO/creating_platform_index.md b/website/translated_docs/no-NO/creating_platform_index.md deleted file mode 100644 index 4a8cab3f..00000000 --- a/website/translated_docs/no-NO/creating_platform_index.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Integration Platforms" -sidebar_label: "Platforms" ---- - -Home Assistant has various built-in integrations that abstract device types. There are [lights](entity_light.md), [switches](entity_switch.md), [covers](entity_cover.md), [climate devices](entity_climate.md), and [many more](entity_index.md). Your integration can hook into these integrations by creating a platform. You will need a platform for each integration that you are integrating with. - -To create a platform, you will need to create a file with the domain name of the integration that you are building a platform for. So if you are building a light, you will add a new file `light.py` to your integration folder. - -We have created two example integrations that should give you a look at how this works: - -- [Example sensor platform](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_sensor/): hello world of platforms. -- [Example light platform](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_light/): showing best practices. - -### Interfacing with devices - -One Home Assistant rule is that the integration should never interface directly with devices. Instead, it should interact with a third-party Python 3 library. This way, Home Assistant can share code with the Python community and keep the project maintainable. - -Once you have your Python library ready and published to PyPI, add it to the [manifest](creating_integration_manifest.md). It will now be time to implement the Entity base class that is provided by the integration that you are creating a platform for. - -Find your integration at the [entity index](entity_index.md) to see what methods and properties are available to implement. \ No newline at end of file diff --git a/website/translated_docs/no-NO/data_entry_flow_index.md b/website/translated_docs/no-NO/data_entry_flow_index.md deleted file mode 100644 index bd2e3b20..00000000 --- a/website/translated_docs/no-NO/data_entry_flow_index.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -title: Data Entry Flow -sidebar_label: Introduction ---- - -Data Entry Flow is a data entry framework that is part of Home Assistant. Data entry is done via data entry flows. A flow can represent a simple login form or a multi-step setup wizard for a component. A Flow Manager is managing all flows that are in progress and handles creation of new flows. - -Data Entry Flow is being used in Home Assistant to create config entries. - -## Flow Manager - -This is the class that manages the flows that are in progress. When instantiating one, you pass in two async callbacks: - -```python -async def async_create_flow(handler, context=context, data=data) -``` - -The manager delegates instantiating of config flow handlers to this async callback. This allows the parent of the manager to define their own way of finding handlers and preparing a handler for instantiation. For example, in the case of the config entry manager, it will make sure that the dependencies and requirements are setup. - -```python -async def async_finish_flow(flow, result) -``` - -This async callback is called when a flow is finished or aborted. i.e. `result['type'] in [RESULT_TYPE_CREATE_ENTRY, RESULT_TYPE_ABORT]`. The callback function can modify result and return it back, if the result type changed to `RESULT_TYPE_FORM`, the flow will continue running, display another form. - -If the result type is `RESULT_TYPE_FORM`, the result should like: - -```python -{ - # The result type of the flow - 'type': RESULT_TYPE_FORM, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # name of the step, flow.async_step_[step_id] will be called when form submitted - 'step_id': 'init', - # a voluptuous schema to build and validate user input - 'data_schema': vol.Schema(), - # an errors dict, None if no errors - 'errors': errors, - # a detail information about the step - 'description_placeholders': description_placeholders, -} -``` - -If the result type is `RESULT_TYPE_CREATE_ENTRY`, the result should like: - -```python -{ - # Data schema version of the entry - 'version': 2, - # The result type of the flow - 'type': RESULT_TYPE_CREATE_ENTRY, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # title and data as created by the handler - 'title': 'Some title', - 'result': { - 'some': 'data' - }, -} -``` - -If the result type is `RESULT_TYPE_ABORT`, the result should like: - -```python -{ - # The result type of the flow - 'type': RESULT_TYPE_ABORT, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # the abort reason - 'reason': 'already_configured', -} -``` - -## Flow Handler - -Flow handlers will handle a single flow. A flow contains one or more steps. When a flow is instantiated, the `FlowHandler.init_step` step will be called. Each step has three different possible results: "Show Form", "Abort" and "Create Entry". - -At a minimum, each flow handler will have to define a version number and a step. This doens't have to be `init`, as `async_create_flow` can assign `init_step` depends on diffreent workflow, for example in configuration, `context.source` will be use as `init_step`. - -The bare minimum config flow: - -```python -from homeassistant import data_entry_flow - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - # The schema version of the entries that it creates - # Home Assistant will call your migrate method if the version changes - # (this is not implemented yet) - VERSION = 1 - - async def async_step_user(self, user_input=None): - # Do something -``` - -### Show Form - -This result type will show a form to the user to fill in. You define the current step, the schema of the data (using voluptuous) and optionally a dictionary of errors. Title and description of the step will be provided via the translation file. Where this is defined depends on the context of the data entry flow. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema) - ) -``` - -After the user has filled in the form, the step method will be called again and the user input is passed in. Your step will only be called if the user input passes your data schema. When the user passes in data, you will have to do extra validation of the data. For example, you can verify that the passed in username and password are valid. - -If something is wrong, you can return a dictionary with errors. Each key in the error dictionary refers to a field name that contains the error. Use the key `base` if you want to show an error unrelated to a specific field. The specified errors need to refer to a key in a translation file. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # See next section on create entry usage - return self.create_entry(...) - - errors['base'] = 'auth_error' - - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema), - errors=errors - ) -``` - -#### Multi-step flows - -If the user input passes validation, you can again return one of the three return values. If you want to navigate the user to the next step, return the return value of that step: - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_init(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # Store info to use in next step - self.init_info = user_input - # Return the form of the next step - return await self.async_step_account() - - ... -``` - -### Create Entry - -When the result is "Create Entry", an entry will be created and passed to the parent of the flow manager. A success message is shown to the user and the flow is finished. You create an entry by passing a title and data. The title can be used in the UI to indicate to the user which entry it is. Data can be any data type, as long as it is JSON serializable. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - return self.create_entry( - title='Title of the entry', - data={ - 'something_special': user_input['username'] - } - ) -``` - -### Abort - -When a flow cannot be finished, you need to abort it. This will finish the flow and inform the user that the flow has finished. Reasons for a flow to not be able to finish can be that a device is already configured or not compatible with Home Assistant. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - return self.async_abort( - reason='not_supported' - ) -``` - -## Translations - -Data entry flows depend on translations for showing the text in the forms. It depends on the parent of a data entry flow manager where this is stored. - -## Initializing a config flow from an external source - -You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing a flow: - -```python -await flow_mgr.async_init('hue', context={'source': data_entry_flow.SOURCE_DISCOVERY}, data=discovery_info) -``` - -The config flow handler will not start with the `init` step. Instead, it will be instantiated with a step name equal to the source. The step should follow the same return values as a normal step. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/dev_101_config.md b/website/translated_docs/no-NO/dev_101_config.md deleted file mode 100644 index e91e5f31..00000000 --- a/website/translated_docs/no-NO/dev_101_config.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Using Config" ---- - -Based on where you are in the code, `config` can mean various things. - -### On the hass object - -On the hass object is an instance of the Config class. The Config class contains the users preferred units, the path to the config directory and which components are loaded. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config) - -### Config passed into component setup - -The `config` parameter passed to a component setup is a dictionary containing all of the user supplied configuration. The keys of the dictionary are the component names and the value is another dictionary with the component configuration. - -The object will have already been validated using your `CONFIG_SCHEMA` or `PLATFORM_SCHEMA` if available. If you have defined a `PLATFORM_SCHEMA`, all references to your component (ie `light 2:` etc) will have been changed to be accessible as a list under `config[DOMAIN]`. - -If your configuration file contains the following lines: - -```yaml -example: - host: paulusschoutsen.nl -``` - -Then in the setup method of your component you will be able to refer to `config['example']['host']` to get the value `paulusschoutsen.nl`. - -### Passed into platform setup - -The `config` parameter passed to a platform setup function is only the config for that specific platform. \ No newline at end of file diff --git a/website/translated_docs/no-NO/dev_101_events.md b/website/translated_docs/no-NO/dev_101_events.md deleted file mode 100644 index f6f38462..00000000 --- a/website/translated_docs/no-NO/dev_101_events.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "Using Events" ---- - -The core of Home Assistant is driven by events. That means that if you want to respond to something happening, you'll have to respond to events. Most of the times you won't interact directly with the event system but use one of the [event listener helpers](https://dev-docs.home-assistant.io/en/master/api/helpers.html#module-homeassistant.helpers.event). - -The event system is very flexible. There are no limitations on the event type, as long as it's a string. Each event can contain data. The data is a dictionary that can contain any data as long as it's JSON serializable. This means that you can use number, string, dictionary and list. - -[List of events that Home Assistant fires.](https://www.home-assistant.io/docs/configuration/events/) - -## Firing events - -To fire an event, you have to interact with the event bus. The event bus is available on the Home Assistant instance as `hass.bus`. - -Example component that will fire an event when loaded. Note that custom event names are prefixed with the component name. - -```python -DOMAIN = 'example_component' - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - # Fire event example_component_my_cool_event with event data answer=42 - hass.bus.fire('example_component_my_cool_event', { - 'answer': 42 - }) - - # Return successful setup - return True -``` - -## Listening to events - -Most of the times you'll not be firing events but instead listen to events. For example, the state change of an entity is broadcasted as an event. - -```python -DOMAIN = 'example_component' - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - count = 0 - - # Listener to handle fired events - def handle_event(event): - nonlocal count - count += 1 - print('Answer {0} is: {1}'.format(count, event.data.get('answer'))) - - # Listen for when example_component_my_cool_event is fired - hass.bus.listen('example_component_my_cool_event', handle_event) - - # Return successful setup - return True -``` - -### Helpers - -Home Assistant comes with a lot of bundled helpers to listen to specific types of event. There are helpers to track a point in time, to track a time interval, a state change or the sun set. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/helpers.html#module-homeassistant.helpers.event) \ No newline at end of file diff --git a/website/translated_docs/no-NO/dev_101_hass.md b/website/translated_docs/no-NO/dev_101_hass.md deleted file mode 100644 index bc8d414e..00000000 --- a/website/translated_docs/no-NO/dev_101_hass.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "Hass object" ---- - -While developing Home Assistant you will see a variable that is everywhere: `hass`. This is the Home Assistant instance that will give you access to all the various parts of the system. - -### The `hass` object - -The Home Assistant instance contains four objects to help you interact with the system. - -| Object | Description | -| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `hass` | This is the instance of Home Assistant. Allows starting, stopping and enqueing new jobs. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.HomeAssistant) | -| `hass.config` | This is the core configuration of Home Assistant exposing location, temperature preferences and config directory path. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config) | -| `hass.states` | This is the StateMachine. It allows you to set states and track when they are changed. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.StateMachine) | -| `hass.bus` | This is the EventBus. It allows you to trigger and listen for events. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.EventBus) | -| `hass.services` | This is the ServiceRegistry. It allows you to register services. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.ServiceRegistry) | - -### Where to find `hass` - -Depending on what you're writing, there are different ways the `hass` object is made available. - -**Component** -Passed into `setup(hass, config)` or `async_setup(hass, config)`. - -**Platform** -Passed into `setup_platform(hass, config, add_devices, discovery_info=None)` or `async_setup_platform(hass, config, async_add_devices, discovery_info=None)`. - -**Entity** -Available as `self.hass` once the entity has been added via the `add_devices` callback inside a platform. \ No newline at end of file diff --git a/website/translated_docs/no-NO/dev_101_index.md b/website/translated_docs/no-NO/dev_101_index.md deleted file mode 100644 index 9cbf54d8..00000000 --- a/website/translated_docs/no-NO/dev_101_index.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Development 101" -sidebar_label: Introduction ---- - -The goal of development 101 is to get you familiar with the basics of developing for Home Assistant. Before we start, please make sure you familiarize yourself with the [architecture](architecture_index.md). - -To get our code running inside Home Assistant we're going to create a custom component. The first step is to locate your config folder. You can find the path to your config folder by opening the Home Assistant frontend, click on the service developer tool icon. It's the path after the text "Path to configuration.yaml". - -Inside your configuration directory create a new folder called `custom_components`. It might be that one already exists, that's fine too. This is the folder that Home Assistant will look at when looking for custom code. - -> The Home Assistant API has two variants: a synchronous and an asynchronous version (asyncio). This development course will focus on the synchronous version. - -To verify that everything is working correctly, let's create a small Hello World component. To do so, create a file called `hello_world.py` in your custom components folder. Copy paste the following content to it: - -```python -# The domain of your component. Equal to the filename of your component. -DOMAIN = "hello_world" - - -def setup(hass, config): - """Setup the hello_world component.""" - # States are in the format DOMAIN.OBJECT_ID. - hass.states.set('hello_world.Hello_World', 'Works!') - - # Return boolean to indicate that initialization was successfully. - return True -``` - -Last step is to add `hello_world:` entry to your `configuration.yaml` file. - -```yaml -# Hello World component -hello_world: -``` - -After running `hass`, we should see log entries stating that `hello_world` component was loaded. What is more, additional state card shall appear within main panel. - -```log -2018-04-03 21:44:20 INFO (MainThread) [homeassistant.loader] Loaded hello_world from custom_components.hello_world -2018-04-03 21:44:20 INFO (MainThread) [homeassistant.setup] Setting up hello_world -``` - -![State card showing that Hello World component is working as intended.](/img/en/frontend/hello-world-state-card.png) \ No newline at end of file diff --git a/website/translated_docs/no-NO/dev_101_services.md b/website/translated_docs/no-NO/dev_101_services.md deleted file mode 100644 index 7bae113c..00000000 --- a/website/translated_docs/no-NO/dev_101_services.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: "Integration Services" -sidebar_label: "Custom Services" ---- - -Home Assistant provides ready-made services for a lot of things, but it doesn't always cover everything. Instead of trying to change Home Assistant, it is preferred to add it as a service under your own integration first. Once we see a pattern in these services, we can talk about generalizing them. - -This is a simple "hello world" example to show the basics of registering a service. To use this example, create the file `/custom_components/hello_service/__init__.py` and copy the below example code. - -Services can be called from automations and from the service "Developer tools" in the frontend. - -```python -DOMAIN = 'hello_service' - -ATTR_NAME = 'name' -DEFAULT_NAME = 'World' - - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - def handle_hello(call): - """Handle the service call.""" - name = call.data.get(ATTR_NAME, DEFAULT_NAME) - - hass.states.set('hello_service.hello', name) - - hass.services.register(DOMAIN, 'hello', handle_hello) - - # Return boolean to indicate that initialization was successfully. - return True -``` - -Load the integration by adding the following to your `configuration.yaml`. When your component is loaded, a new service should be available to call. - -```yaml -# configuration.yaml entry -hello_service: -``` - -Open the frontend and in the sidebar, click the first icon in the developer tool section. This will open the Call Service developer tool. On the right, find your service and click on it. This will automatically fill in the correct values. - -Pressing "Call Service" will now call your service without any parameters. This will cause your service to create a state with the default name 'World'. If you want to specify the name, you have to specify parameters. Add the following JSON as Service Data and press "Call Service again". - -```json -{ - "name": "Planet" -} -``` - -The service will now overwrite the previous state with "Planet". - -## Service descriptions - -Adding services is only useful if users know about them. In Home Assistant we use a `services.yaml` as part of your integration to describe the services. - -Services are published under the domain name of your integration, so in `services.yaml` we only use the service name as the base key. - -```yaml -# Example services.yaml entry - -set_speed: - # Description of the service - description: Sets fan speed. - # Different fields that your service accepts - fields: - # Key of the field - entity_id: - # Description of the field - description: Name(s) of the entities to set - # Example value that can be passed for this field - example: 'fan.living_room' - speed: - description: Speed setting - example: 'low' -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/dev_101_states.md b/website/translated_docs/no-NO/dev_101_states.md deleted file mode 100644 index d35379c7..00000000 --- a/website/translated_docs/no-NO/dev_101_states.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -title: "Using States" ---- - -Home Assistant keeps track of the states of entities in a state machine. The state machine has very few requirements: - -- Each state is related to an entity identified by an entity id. This id is made up of a domain and an object id. For example `light.kitchen_ceiling`. You can make up any combination of domain and object id, even overwriting existing states. -- Each state has a primary attribute that describes the state of the entity. In the case of a light this could be for example "on" and "off". You can store anything you want in the state, as long as it's a string (will be converted if it's not). -- You can store more information about an entity by setting attributes. Attributes is a dictionary that can contain any data that you want. The only requirement is that it's JSON serializable, so you're limited to numbers, strings, dictionaries and lists. - -[Description of the state object.](https://www.home-assistant.io/docs/configuration/state_object/) - -## Using states in your component - -This is a simple tutorial/example on how to create and set states. We will do our work in a component called "hello_state". The purpose of this component is to display a given text in the frontend. - -To get started, create the file `/custom_components/hello_state.py` and copy the below example code. - -```python -""" -Support for showing text in the frontend. - -For more details about this component, please refer to the documentation at -https://home-assistant.io/cookbook/python_component_basic_state/ -""" -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = 'hello_state' - -def setup(hass, config): - """Setup the Hello State component. """ - _LOGGER.info("The 'hello state' component is ready!") - - return True -``` - -1. In the file header we decided to add some details: A short description and the link to the documentation. -2. We want to do some logging. This means that we import the Python logging module and create an alias. -3. The component name is equal to the domain name. -4. The `setup` function will take care of the initialization of our component. The component will only write a log message. Keep in mind for later that you have several options for the severity: - -- `_LOGGER.info(msg)` -- `_LOGGER.warning(msg)` -- `_LOGGER.error(msg)` -- `_LOGGER.critical(msg)` -- `_LOGGER.exception(msg)` - -5. We return `True` if everything is ok. - -Add the component to your `configuration.yaml` file. - -```yaml -hello_state: -``` - -After a start or a restart of Home Assistant the component will create an entry in the log. - -```bash -16-03-12 14:16:42 INFO (MainThread) [custom_components.hello_state] The 'hello state' component is ready! -``` - -The next step is the introduction of configuration options. A user can pass configuration options to our component via `configuration.yaml`. To use them we'll use the passed in `config` variable to our `setup` method. - -```python -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = 'hello_state' - -CONF_TEXT = 'text' -DEFAULT_TEXT = 'No text!' - -def setup(hass, config): - """Set up the Hello State component. """ - # Get the text from the configuration. Use DEFAULT_TEXT if no name is provided. - text = config[DOMAIN].get(CONF_TEXT, DEFAULT_TEXT) - - # States are in the format DOMAIN.OBJECT_ID - hass.states.set('hello_state.Hello_State', text) - - return True -``` - -To use the latest feature of our component, update the entry in your `configuration.yaml` file. - -```yaml -hello_state: - text: 'Hello, World!' -``` - -Thanks to `DEFAULT_TEXT` variable the component will launch even if no `text:` field is used in the `configuration.yaml` file. Quite often there are variables which are required. It's important to check if all mandatory configuration variables are provided. If not, the setup should fail. We will use `voluptuous` as a helper to achieve this. The next listing shows the essential parts. - -```python -import voluptuous as vol - -import homeassistant.helpers.config_validation as cv - -CONFIG_SCHEMA = vol.Schema({ - DOMAIN: vol.Schema({ - vol.Required(CONF_TEXT): cv.string, - }) -}, extra=vol.ALLOW_EXTRA) -``` - -Now, when `text:` is missing from the config, Home Assistant will alert the user and not setup your component. - -After a start or a restart of Home Assistant the component will be visible in the frontend if the `configuration.yaml` file is up-to-date. - -

- -

- -In order to expose attributes for a platform, you will need to define a property called `device_state_attributes` on the entity class, which will return a dictionary of attributes: - - @property - def device_state_attributes(self): - """Return device specific state attributes.""" - return self._attributes - - -> Entities also have a similar property `state_attributes`, which normally doesn't need to be defined by new platforms. This property is used by base components to add standard sets of attributes to a state. Example: The light component uses `state_attributes` to add brightness to the state dictionary. If you are designing a new component, you should define `state_attributes` instead. - -To get your component included in the Home Assistant releases, follow the steps described in the [Submit your work](development_submitting.md) section. Basically you only need to move your component in the `homeassistant/component/` directory of your fork and create a Pull Request. \ No newline at end of file diff --git a/website/translated_docs/no-NO/development_catching_up.md b/website/translated_docs/no-NO/development_catching_up.md deleted file mode 100644 index 7f14f6d5..00000000 --- a/website/translated_docs/no-NO/development_catching_up.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Catching up with Reality" ---- - -If it's taking a while to develop your feature, and you want to catch up with what's in the current Home Assistant `dev` branch, you can use `git rebase`. This will pull the latest Home Assistant changes locally, rewind your commits, bring in the latest changes from Home Assistant, and replay all of your commits on top. - -> If you use the workflow below, it is important that you force push the update as described. Git might prompt you to do `git pull` first. Do **NOT** do that! It would mess up your commit history. - -```bash -# Run this from your feature branch -$ git fetch upstream dev # to pull the latest changes into a local dev branch -$ git rebase upstream/dev # to put those changes into your feature branch before your changes -``` - -If rebase detects conflicts, repeat this process until all changes have been resolved: - -1. `git status` shows you the file with the conflict; edit the file and resolve the lines between `<<<< | >>>>` -2. Add the modified file: `git add ` or `git add .` -3. Continue rebase: `git rebase --continue` -4. Repeat until you've resolved all conflicts - -After rebasing your branch, you will have rewritten history relative to your GitHub fork's branch. When you go to push you will see an error that your history has diverged from the original branch. In order to get your GitHub fork up-to-date with your local branch, you will need to force push, using the following command: - -```bash -# Run this from your feature branch -$ git push origin --force -``` - -Other workflows are covered in detail in the [Github documentation](https://help.github.com/articles/fork-a-repo/). Add an additional `remote` after you clone your fork. - -```bash -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -Then, `git pull --rebase upstream dev`. \ No newline at end of file diff --git a/website/translated_docs/no-NO/development_checklist.md b/website/translated_docs/no-NO/development_checklist.md deleted file mode 100644 index 0d1652cd..00000000 --- a/website/translated_docs/no-NO/development_checklist.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "Development Checklist" -sidebar_label: Introduction ---- - - -Before you commit any changes, check your work against these requirements: - -- All communication to external devices or services must be wrapped in an external Python library hosted on [pypi](https://pypi.python.org/pypi). -- New dependencies are added to `requirements_all.txt` (if applicable), using `python3 -m script.gen_requirements_all` -- New codeowners are added to `CODEOWNERS` (if applicable), using `python3 -m script.hassfest` -- The `.coveragerc` file is updated to exclude your platform if there are no tests available or your new code uses a third-party library for communication with the device, service, or sensor -- Documentation is developed for [home-assistant.io](https://home-assistant.io/) - - Visit the [website documentation](https://www.home-assistant.io/developers/documentation/) for more information about contributing to [home-assistant.io](https://github.com/home-assistant/home-assistant.github.io). \ No newline at end of file diff --git a/website/translated_docs/no-NO/development_environment.md b/website/translated_docs/no-NO/development_environment.md deleted file mode 100644 index 9e0bc03c..00000000 --- a/website/translated_docs/no-NO/development_environment.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -title: "Set up Development Environment" ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example CentOS would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Due to Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run - -```bash -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is set up, perform install as for Linux. - -```bash -$ sudo apt-get update -$ sudo apt-get install python3-pip python3-dev python3-venv -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```bash -$ mkdir -p ../config -$ hass -c ../config -``` - -### Developing on OS X - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 autoconf -``` - -Then install ffmpeg: - -```bash -$ brew install ffmpeg -``` - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv venv -$ source venv/bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```bash -$ hass -``` - -## Logging - -By default logging in Home Assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/development_guidelines.md b/website/translated_docs/no-NO/development_guidelines.md deleted file mode 100644 index 0383618a..00000000 --- a/website/translated_docs/no-NO/development_guidelines.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: "Style guidelines" ---- - -Home Assistant enforces strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. We automatically test every pull request as part of the linting process. - -Summary of the most relevant points: - -- Line length is limited to 79 characters (see below). -- Use 4 spaces per indentation level. We don't use tabs. -- Comments should be full sentences and end with a period. -- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered. -- Constants and the content of lists and dictionaries should be in alphabetical order. -- Avoid trailing whitespace but surround binary operators with a single space. -- Line separator should be set to `LF`. - -The maximum line length comes directly from the [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/#maximum-line-length), and is also used by the Python standard library. All code must pass these linting checks, and no exceptions will be made. There have already been numerous requests to increase the maximum line length, but after evaluating the options, the Home Assistant maintainers have decided to stay at 79 characters. This decision is final. - -Those points may require that you adjust your IDE or editor settings. - -## Our recommendations - -For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code unified. - -### Quotes - -Use single quotes `'` for single word and `"` for multiple words or sentences. - -```python -ATTR_WATERLEVEL = 'level' -CONF_ATTRIBUTION = "Data provided by the WUnderground weather service" -SENSOR_TYPES = { - 'alerts': ['Alerts', None], -} -``` - -### File headers - -The docstring in the file header should describe what the file is about. - -```python -"""Support for MQTT lights.""" -``` - -### Log messages - -There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. Try to avoid brackets and additional quotes around the output to make it easier for users to parse the log. A widely style is shown below but you are free to compose the messages as you like. - -```python -_LOGGER.error("No route to device: %s", self._resource) -``` - -```bash -2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18 -``` - -Don't print out wrong API keys, tokens, usernames, or passwords. Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` in anything else. - -### Ordering of imports - -Instead of order the imports manually, use [`isort`](https://github.com/timothycrosley/isort). - -```bash -$ pip3 install isort -$ isort homeassistant/components/sensor/fixer.py -``` - -### Use new style string formatting - -Prefer [new style string formatting](https://www.python.org/dev/peps/pep-3101/) over old. - -```python -"{} {}".format('New', 'style') -"%s %s" % ('Old', 'style') -``` - -Except when doing logging here the format is: - -```python -_LOGGER.info("Can't connect to the webservice %s at %s", string1, string2) -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/development_index.md b/website/translated_docs/no-NO/development_index.md deleted file mode 100644 index d0557fd3..00000000 --- a/website/translated_docs/no-NO/development_index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: "Starting with Development" -sidebar_label: Introduction ---- - -Home Assistant is built from the ground up to be easily extensible using integrations. In this section, we're focusing on how to develop integrations. - -Before you start, make sure that you have read up on the [Home Assistant architecture](architecture_index.md) so that you are familiar with the concepts that make up Home Assistant. - -If you run into trouble following this documentation, don't hesitate to join our #devs_backend channel on [Discord](https://www.home-assistant.io/join-chat/). \ No newline at end of file diff --git a/website/translated_docs/no-NO/development_submitting.md b/website/translated_docs/no-NO/development_submitting.md deleted file mode 100644 index 5f0bac56..00000000 --- a/website/translated_docs/no-NO/development_submitting.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Submit your work" ---- - -> Always base your Pull Requests of of the current **`dev`** branch, not `master`. - -Submit your improvements, fixes, and new features to Home Assistant one at a time, using GitHub [Pull Requests](https://help.github.com/articles/using-pull-requests). Here are the steps: - -1. From your fork's dev branch, create a new branch to hold your changes: - - `git checkout -b some-feature` - -2. Make your changes, create a [new platform](creating_platform_index.md), develop a [new component](creating_component_index.md), or fix [issues](https://github.com/home-assistant/home-assistant/issues). - -3. [Test your changes](development_testing.md) and check for style violations. - -4. If everything looks good according to these [musts](development_checklist.md), commit your changes: - - `git add .` - - `git commit -m "Add some-feature"` - - - Write a meaningful commit message and not only `Update` or `Fix`. - - Use a capital letter to start with your commit message. - - Don't prefix your commit message with `[bla.bla]` or `platform:`. - - Consider adding tests to ensure that your code works. - -5. Push your committed changes back to your fork on GitHub: - - `git push origin HEAD` - -6. Follow [these steps](https://help.github.com/articles/creating-a-pull-request/) to create your pull request. - - - On GitHub, navigate to the main page of the Home Assistant repository. - - In the "Branch" menu, choose the branch that contains your commits (from your fork). - - To the right of the Branch menu, click **New pull request**. - - Use the base branch dropdown menu to select the branch you'd like to merge your changes into, then use the compare branch drop-down menu to choose the topic branch you made your changes in. Make sure the Home Assistant branch matches with your forked branch (`dev`) else you will propose ALL commits between branches. - - Type a title and complete the provided description for your pull request. - - Click **Create pull request**. - -7. Check for comments and suggestions on your pull request and keep an eye on the [CI output](https://travis-ci.org/home-assistant/home-assistant/). \ No newline at end of file diff --git a/website/translated_docs/no-NO/development_testing.md b/website/translated_docs/no-NO/development_testing.md deleted file mode 100644 index 2b57f7e1..00000000 --- a/website/translated_docs/no-NO/development_testing.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: "Testing your code" ---- - -As it states in the [Style guidelines section](development_guidelines.md) all code is checked to verify the following: - -- All the unit tests pass -- All code passes the checks from the linting tools - -Local testing is done using Tox, which has been installed as part of running `script/setup` in the [virtual environment](development_environment.md). To start the tests, activate the virtual environment and simply run the command: - -```bash -$ tox -``` - -**Important:** Run `tox` before you create your pull request to avoid annoying fixes. - -Running Tox will run unit tests against the locally available Pythons, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one tox target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py36` runs unit tests only on Python 3.6. - -Tox uses virtual environments under the hood to create isolated testing environments. The tox virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell Tox to recreate the virtual environments. - -OSX users may see an `Error creating virtualenv` when runnng `tox`. If this occurs, install the [tox-venv](https://pypi.org/project/tox-venv/) package using the command `pip install tox-venv` and try again. - -### Adding new dependencies to test environment - -If you are working on tests for a component or platform and you need the dependencies available inside the Tox environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments. - -### Running single tests using Tox - -You can pass arguments via Tox to py.test to be able to run single test suites or test files. Replace `py36` with the Python version that you use. - -```bash -# Stop after the first test fails -$ tox -e py36 -- tests/test_core.py -x -# Run test with specified name -$ tox -e py36 -- tests/test_core.py -k test_split_entity_id -# Fail a test after it runs for 2 seconds -$ tox -e py36 -- tests/test_core.py --timeout 2 -# Show the 10 slowest tests -$ tox -e py36 -- tests/test_core.py --duration=10 -``` - -### Testing outside of Tox - -Running tox will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without Tox, you'll need to install the test dependencies into your Python environment: - -```bash -$ pip3 install -r requirements_test_all.txt -c homeassistant/package_constraints.txt -``` - -Now that you have all test dependencies installed, you can run tests on individual files: - -```bash -$ flake8 homeassistant/core.py -$ pylint homeassistant/core.py -$ pydocstyle homeassistant/core.py -$ py.test tests/test_core.py -``` - -You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script: - -```bash -$ script/lint -``` - -### Preventing Linter Errors - -Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them! - -```bash -$ pip3 install flake8 flake8-docstrings -$ flake8 --install-hook=git -``` - -The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8. - -### Notes on PyLint and PEP8 validation - -If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member. \ No newline at end of file diff --git a/website/translated_docs/no-NO/development_typing.md b/website/translated_docs/no-NO/development_typing.md deleted file mode 100644 index 81f153cd..00000000 --- a/website/translated_docs/no-NO/development_typing.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: "Adding type hints to your code" ---- - -Type hints in Python are static annotations of variables and functions, to let humans more easily understand the code. See the standard library [docs](https://docs.python.org/3/library/typing.html) and this PyCascades 2018 [talk](https://youtu.be/zKre4DKAB30). - -Type hints are not required for all modules at the moment in Home Assistant, but we aim to have complete coverage of the core modules. - -Adding type hints to an existing codebase can be a daunting task. To speed this up and help developers doing this, Instagram made the [`monkeytype`](https://pypi.org/project/MonkeyType/) program. It will analyze calls during runtime and try to assign the correct type hints to the code. - -See [this instagram blog post](https://instagram-engineering.com/let-your-code-type-hint-itself-introducing-open-source-monkeytype-a855c7284881) for a description of the workflow involved to use the monkeytype program. - -We've added a script to start a run of our test suite or a test module and tell the `monkeytype` program to analyze the run. - -### Basic workflow - -1. Run `script/monkeytype tests/path/to/your_test_module.py`. -2. Run `monkeytype stub homeassistant.your_actual_module`. -3. Look at output from the monkeytyped typing stub. If not totally bad, apply the stub to your module. You most likely will need to manually edit the typing in the last step. -4. Run `monkeytype apply homeassistant.your_actual_module`. -5. Check the diff and manually correct the typing if needed. Commit, push the branch and make a PR. - -**Note:** Applying a monkeytyped stub to a module that has existing typing annotations might error and not work. This tool is most useful for totally untyped modules. \ No newline at end of file diff --git a/website/translated_docs/no-NO/development_validation.md b/website/translated_docs/no-NO/development_validation.md deleted file mode 100644 index 9e7770a7..00000000 --- a/website/translated_docs/no-NO/development_validation.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: "Validate the input" ---- - -The `configuration.yaml` file contains the configuration options for components and platforms. We use [voluptuous](https://pypi.python.org/pypi/voluptuous) to make sure that the configuration provided by the user is valid. Some entries are optional or could be required to set up a platform or a component. Others must be a defined type or from an already-defined list. - -We test the configuration to ensure that users have a great experience and minimize notifications if something is wrong with a platform or component setup before Home Assistant runs. - -Besides [voluptuous](https://pypi.python.org/pypi/voluptuous) default types, many custom types are available. For an overview, take a look at the [config_validation.py](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/config_validation.py) helper. - -- Types: `string`, `byte`, and `boolean` -- Entity ID: `entity_id` and `entity_ids` -- Numbers: `small_float` and `positive_int` -- Time: `time`, `time_zone` -- Misc: `template`, `slug`, `temperature_unit`, `latitude`, `longitude`, `isfile`, `sun_event`, `ensure_list`, `port`, `url`, and `icon` - -To validate platforms using [MQTT](https://www.home-assistant.io/components/mqtt/), `valid_subscribe_topic` and `valid_publish_topic` are available. - -Some things to keep in mind: - -- Use the constants defined in `const.py` -- Import `PLATFORM_SCHEMA` from the integration you are integrating with and extend it. -- Preferred order is `required` first and `optional` second -- Default values for optional configuration keys need to be valid values. Don't use a default which is `None` like `vol.Optional(CONF_SOMETHING, default=None): cv.string`, set the default to `default=''` if required. - -### Snippets - -This section contains snippets for the validation we use. - -#### Default name - -It's common to set a default for a sensor if the user doesn't provide a name to use. - -```python -DEFAULT_NAME = 'Sensor name' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, -``` - -#### Limit the values - -You might want to limit the user's input to a couple of options. - -```python -DEFAULT_METHOD = 'GET' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): vol.In(['POST', 'GET']), -``` - -#### Port - -All port numbers are from a range of 1 to 65535. - -```python -DEFAULT_PORT = 993 - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, -``` - -#### Lists - -If a sensor has a pre-defined list of available options, test to make sure the configuration entry matches the list. - -```python -SENSOR_TYPES = { - 'article_cache': ('Article Cache', 'MB'), - 'average_download_rate': ('Average Speed', 'MB/s'), -} - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_MONITORED_VARIABLES, default=[]): - vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/device_registry_index.md b/website/translated_docs/no-NO/device_registry_index.md deleted file mode 100644 index 394002ea..00000000 --- a/website/translated_docs/no-NO/device_registry_index.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Device Registry -sidebar_label: Introduction ---- - -The device registry is a registry where Home Assistant keeps track of devices. A device is represented in Home Assistant via one or more entities. For example, a battery-powered temperature and a humidity sensor might expose entities for temperature, humidity and battery level. - -![Device registry overview](/img/en/device_registry/overview.png) - -## What is a device? - -A device in Home Assistant represents a physical device that has its own control unit. The control unit itself does not have to be smart, but it should be in control of what happens. For example, an Ecobee thermostat with 4 room sensors equals 5 devices in Home Assistant, one for the thermostat including all sensors inside it, and one for each sensor. - -If you connect a sensor to another device to read some of its data, it should still be represented as two different devices. The reason for this is that the sensor could be moved to read the data of another device. - -> Although not currently available, we could consider offering an option to users to merge devices. - -## Device properties - -| Attribute | Description | -| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| id | Unique ID of device (generated by Home Assistant) | -| name | Name of this device | -| connections | A set of tuples of `(connection_type, connection identifier)`. Connection types are defined in the device registry module. | -| identifiers | Set of identifiers. They identify the device in the outside world. An example is a serial number. | -| manufacturer | The manufacturer of the device. | -| model | The model of the device. | -| config_entries | Config entries that are linked to this device. | -| sw_version | The firmware version of the device. | -| via_hub | Identifier of a device that routes messages between this device and Home Assistant. Examples of such devices are hubs. This is used to show device topology in Home Assistant. | -| area_id | The Area which the device is placed in. | - -## Defining devices - -> Entity device info is only read if the entity is loaded via a [config entry](config_entries_index.md). - -Each entity is able to define a device via the `device_info` property. This property is read when an entity is added to Home Assistant via a config entry. A device will be matched up with an existing device via supplied identifiers and connections, like serial numbers or MAC addresses. - -```python -# Inside a platform -class HueLight(LightEntity): - - @property - def device_info(self): - return { - 'identifiers': { - # Serial numbers are unique identifiers within a specific domain - (hue.DOMAIN, self.unique_id) - }, - 'name': self.name, - 'manufacturer': self.light.manufacturername, - 'model': self.light.productname, - 'sw_version': self.light.swversion, - 'via_hub': (hue.DOMAIN, self.api.bridgeid), - } - -``` - -Components are also able to register devices in the case that there are no entities representing them. An example is a hub that communicates with the lights. - -```python -# Inside a component -from homeassistant.helpers import device_registry as dr - -device_registry = await dr.async_get_registry(hass) - -device_registry.async_get_or_create( - config_entry=entry.entry_id, - connections={ - (dr.CONNECTION_NETWORK_MAC, config.mac) - }, - identifiers={ - (DOMAIN, config.bridgeid) - }, - manufacturer='Signify', - name=config.name, - model=config.modelid, - sw_version=config.swversion, -) -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/documentation_create_page.md b/website/translated_docs/no-NO/documentation_create_page.md deleted file mode 100644 index e1669a55..00000000 --- a/website/translated_docs/no-NO/documentation_create_page.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: "Create a new page" ---- - -For a platform or component page, the fastest way is to make a copy of an existing page and edit it. The [Component overview](https://www.home-assistant.io/components/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages. - -Please honor the [Standards](documentation_standards.md) we have for the documentation. - -If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers. - -```text ---- -layout: page -title: "Awesome Sensor" -description: "home-assistant.io web presence" -date: 2015-06-17 08:00 -sidebar: true -comments: false -sharing: true -footer: true -ha_release: "0.38" -ha_category: Sensor -ha_iot_class: "Local Polling" -ha_qa_scale: silver ---- - -Content... Written in markdown. - -### {% linkable_title Linkable Header %} -... -``` - -Please keep in mind that if the `date:` entry is in the future then the page will not show up. - -Additional keys for the file header: - -- `logo`: Please check the separate section below. -- `ha_release`: The release when the integration was included, e.g., "0.38". If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`. -- `ha_category`: This entry is used to group the integration on the [Components overview](https://www.home-assistant.io/components/). -- `ha_iot_class`: [IoT class](https://www.home-assistant.io/blog/2016/02/12/classifying-the-internet-of-things) is the classifier for the device's behavior. -- `ha_qa_scale`: [Quality scale](https://www.home-assistant.io/docs/quality_scale/) is the representation of the integration's quality. - -There are [pre-defined variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation. - -A couple of points to remember: - -- Document the needed steps to retrieve API keys or access token for the third party service or device if needed. -- Add screenshots to support the user where it makes sense. -- Add the type of the device(s) (incl. firmware) you have tested when you know that there are multiple out there. - -### Configuration - -Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file. - -The **Configuration Variables** section must use the `{% configuration %} ... {% endconfiguration %}` tag. - -```text -{% configuration %} -api_key: - description: The API key to access the service. - required: true - type: string -name: - description: Name to use in the frontend. - required: false - default: The default name to use in the frontend. - type: string -monitored_conditions: - description: Conditions to display in the frontend. - required: true - type: map - keys: - weather: - description: A human-readable text summary. - temperature: - description: The current temperature. -{% endconfiguration %} -``` - -Available keys: - -- **`description:`**: That the variable is about. -- **`required:`**: If the variable is required. - -```text -required: true #=> Required -required: false #=> Optional -required: inclusive #=> Inclusive -required: exclusive #=> Exclusive -required: any string here #=> Any string here -``` - -- **`type:`**: The type of the variable. Allowed entries: `boolean`, `string`, `integer`, `float`, `time`, `template`, `device_class`, `icon` or `map`/`list` (for a list of entries). For multiple possibilities use `[string, integer]`. If you use `map`/`list` then should define `keys:` (see the [`template` sensor](https://www.home-assistant.io/components/sensor.template/) for an example). If you use `boolean`, then `default:` must be defined. -- **`default:`**: The default value for the variable. - -### Embedding Code - -You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in back-ticks. - -When you're writing code that is to be executed on the terminal, prefix it with `$`. - -### Templates - -For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) [Jinja](http://jinja.pocoo.org/) is used. Check the [Documentation Standards](documentation_standards.md) for further details. - -If you are don't escape templates then they will be rendered and appear blank on the website. - -### HTML - -The direct usage of HTML is supported but not recommended. The note boxes are an exception. - -```html -

- You need to enable telnet on your router. -

-``` - -### Images, icons and logos - -The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent. - -| Type | Location | -|:----------- |:------------------------------ | -| logos | source/images/supported_brands | -| blog | source/images/blog | -| screenshots | source/images/components | - -Not everything (product, component, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/). - -### Linking From The Sidebar - -If you are adding a new page that requires linking from the sidebar, you need to edit the `docs_navigation.html` file in `source/_includes/asides/docs_navigation.html`. \ No newline at end of file diff --git a/website/translated_docs/no-NO/documentation_index.md b/website/translated_docs/no-NO/documentation_index.md deleted file mode 100644 index d196169c..00000000 --- a/website/translated_docs/no-NO/documentation_index.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "Documentation" ---- - -The user documentation is located at . This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. You work on your change and propose it via a Pull Request (PR). - -Once you've created a Pull Request (PR), you can see a preview of the proposed changes by clicking *Details* against Netlify checker in the checkers section of the PR as soon as deployment is complete. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process of working on the website is no different from working on Home Assistant itself. - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.3.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` (You might have to run this command as `sudo`). -- Fork the home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.io). -- In your home-assistant.io root directory, run `$ bundle` to install the gems you need. - -- Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` - -- Shortcut for Debian/Ubuntu: `$ sudo apt-get install ruby ruby-dev ruby-bundler ruby-json g++ zlib1g-dev && bundle` - -Then you can work on the documentation: - -- Run `bundle exec rake generate` to generate the very first preview. This will take a couple of minutes. -- Create/edit/update a page. The components/platforms documentation is located in `source/_components/`. `source/_docs/` contains the Home Assistant documentation itself. -- Test your changes to home-assistant.io locally: run `bundle exec rake preview` and navigate to . While this command is working, any changes to a file are automatically detected and will update the affected pages. You will have to manually reload them in the browser though. -- Create a Pull Request (PR) against the **next** branch of home-assistant.io if your documentation is a new feature, platform, or component. -- Create a Pull Request (PR) against the **current** branch of home-assistant.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -The site generated by `bundle exec rake` is only available locally. If you are developing on a headless machine, use port forwarding: - -```bash -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` - -## Speeding up site generation - -Every release we post long changelogs to the website. This slows down generation of the website significantly! We include some tools to temporarily exclude components and blog posts that you're not working on out of the way. - -```bash -bundle exec rake isolate[filename-of-blogpost-or-component] -``` - -When you're done working on the site, run the following command to move the pages back again: - -```bash -bundle exec rake integrate -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/documentation_standards.md b/website/translated_docs/no-NO/documentation_standards.md deleted file mode 100644 index d0ae54d1..00000000 --- a/website/translated_docs/no-NO/documentation_standards.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: "Standards" ---- - -To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation. - -## General Documentation - -* The language of the documentation should be American-English. -* Don't put two spaces after a period and avoid the "Oxford comma". -* There is no limit for the line length. You are allowed to write in a flowing text style. This will make it easier to use the GitHub online editor in the future. -* Be objective and not gender favoring, polarizing, race related or religion inconsiderate. -* The case of brand names, services, protocols, components and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select". -* All headings should use the `{% linkable_title %}` tag. -* Do not use ALL CAPITALS for emphasis - use italics instead. - -## Component and Platform Pages - -* The **Configuration Variables** section must use the `{% configuration %}` tag. -* Configuration variables must document the requirement status (`false` or `true`). -* Configuration variables must document the default value, if any. -* Configuration variables must document the accepted value types (see [Configuration variables details](documentation_create_page.md#configuration)). - * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`). -* Use YAML sequence syntax in the sample code if it is supported. -* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated. - * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`. - * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note. -* Component and platform names should be a link to their respective documentation pages. - -Example configuration block - -```yaml -{% configuration %} -some_key: - description: This is a description of what this key is for. - required: false - type: string - default: Optional default value - leave out if there isn't one -{% endconfiguration %} -``` - -## Templates - -* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the `{% raw %}` tag. -* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`. -* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)): - * `friendly_name` - * Single-line templates: - * `value_template` - * `level_template` - * `icon_template` - * Children of `data_template` -* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks): - * Strings inside of templates: - * States - * Entity IDs - * `unit_of_measurement` -* No whitespace around pipe character (`|`) for Jinja2 filters. -* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}). -* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}). -* Do not quote values for: - * `device_class` - * `platform` - * `condition` - * `service` - -## Renaming Pages - -It can happen that a component or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old component/platform name, to the page in a [note](/developers/documentation/create_page/#html). - -```text ---- -... -redirect_from: /getting-started/android/ ---- -``` - -Adding a redirect also applies if you move content around in the [documentation](/docs/). - -## Single vs. Double Quotation Marks - -Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required). - -### Examples - -#### Double Quotes Outside, Single Quotes Inside (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}" -``` - -#### Single Quotes Outside, Double Quotes Inside (Invalid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}' -``` - -#### Multi-Line Template (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: >- - {% if trigger.to_state.name == 'Dale\'s Bedroom' %} - Someone's in your base, killing your noobs! - {% else %} - It's just another door. - {% endif %} -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_air_quality.md b/website/translated_docs/no-NO/entity_air_quality.md deleted file mode 100644 index 81c10f5c..00000000 --- a/website/translated_docs/no-NO/entity_air_quality.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Air Quality Entity -sidebar_label: Air Quality ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ---------------------------- | ----- | ------------ | --------------------------------------------- | -| particulate_matter_2_5 | float | **Required** | The particulate matter 2.5 (<= 2.5 μm) level. | -| particulate_matter_10 | float | **Required** | The particulate matter 10 (<= 10 μm) level. | -| particulate_matter_0_1 | float | `None` | The particulate matter 0.1 (<= 0.1 μm) level. | -| air_quality_index | float | `None` | The Air Quality Index (AQI). | -| ozone | float | `None` | The O3 (ozone) level. | -| carbon_monoxide | float | `None` | The CO (carbon monoxide) level. | -| carbon_dioxide | float | `None` | The CO2 (carbon dioxide) level. | -| sulphur_dioxide | float | `None` | The SO2 (sulphur dioxide) level. | -| nitrogen_oxide | float | `None` | The N2O (nitrogen oxide) level. | -| nitrogen_monoxide | float | `None` | The NO (nitrogen monoxide) level. | -| nitrogen_dioxide | float | `None` | The NO2 (nitrogen dioxide) level. | -| volatile_organic_compounds | float | `None` | The volatile organic compounds (VOC) level. | - -Properties have to follow the units defined in the `unit_system`. \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_alarm_control_panel.md b/website/translated_docs/no-NO/entity_alarm_control_panel.md deleted file mode 100644 index 9dc91192..00000000 --- a/website/translated_docs/no-NO/entity_alarm_control_panel.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Alarm Control Panel Entity -sidebar_label: Alarm Control Panel ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ----------- | ------ | ------------ | --------------------------------------------------------- | -| state | string | **Required** | One of the states listed in the **states** section. | -| code_format | string | `None` | One of the states listed in the **code formats** section. | -| changed_by | string | `None` | Last change triggered by. | - -### States - -| Value | Description | -| ---------------------- | ------------------------------------------- | -| `disarmed` | The alarm is disarmed (`off`). | -| `armed_home` | The alarm is armed in home mode. | -| `armed_away` | The alarm is armed in away mode. | -| `armed_night` | The alarm is armed in night mode. | -| `armed_custom_bypass`  | The alarm is armed in bypass mode. | -| `pending` | The alarm is pending (towards `triggered`). | -| `arming` | The alarm is arming. | -| `disarming` | The alarm is disarming. | -| `triggered` | The alarm is triggered. | - -### Code Formats - -| Value | Description | -| ------ | ------------------------------------------------- | -| None | No code required. | -| Number | Code is a number (Shows ten-key pad on frontend). | -| Any | Code is a string. | - -## Methods - -### Alarm Disarm - -Send disarm command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_disarm(self, code=None) -> None: - """Send disarm command.""" - - async def async_alarm_disarm(self, code=None) -> None: - """Send disarm command.""" -``` - -### Alarm Arm Home - -Send arm home command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_home(self, code=None) -> None: - """Send arm home command.""" - - def async_alarm_arm_home(self, code=None) -> None: - """Send arm home command.""" -``` - -### Alarm Arm Away - -Send arm away command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_away(self, code=None) -> None: - """Send arm away command.""" - - def async_alarm_arm_away(self, code=None) -> None: - """Send arm away command.""" -``` - -### Alarm Arm Night - -Send arm night command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_night(self, code=None) -> None: - """Send arm night command.""" - - def async_alarm_arm_night(self, code=None) -> None: - """Send arm night command.""" -``` - -### Alarm Trigger - -Send alarm trigger command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_trigger(self, code=None) -> None: - """Send alarm trigger command.""" - - def async_alarm_trigger(self, code=None) -> None: - """Send alarm trigger command.""" -``` - -### Alarm Custom Bypass - -Send arm custom bypass command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_custom_bypass(self, code=None) -> None: - """Send arm custom bypass command.""" - - def async_alarm_arm_custom_bypass(self, code=None) -> None: - """Send arm custom bypass command.""" -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_binary_sensor.md b/website/translated_docs/no-NO/entity_binary_sensor.md deleted file mode 100644 index 1a791ddb..00000000 --- a/website/translated_docs/no-NO/entity_binary_sensor.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Binary Sensor Entity -sidebar_label: Binary Sensor ---- - -A binary sensor is a sensor that can only have two states. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------ | ------- | ------------ | -------------------------------------------- | -| is_on | boolean | **Required** | If the binary sensor is currently on or off. | -| device_class | string | `None` | Type of binary sensor. | - -### Available device classes - -| Value | Description | -| ------------ | ------------------------------------------------------ | -| battery | On means low, Off means normal. | -| cold | On means cold, Off means normal. | -| connectivity | On means connected, Off means disconnected. | -| door | On means open, Off means closed. | -| garage_door | On means open, Off means closed. | -| gas | On means gas detected, Off means no gas (clear). | -| heat | On means hot, Off means normal. | -| light | On means light detected, Off means no light. | -| lock | On means open (unlocked), Off means closed (locked). | -| moisture | On means wet, Off means dry. | -| motion | On means motion detected, Off means no motion (clear). | -| moving | On means moving, Off means not moving (stopped). | -| occupancy | On means occupied, Off means not occupied (clear). | -| opening | On means open, Off means closed. | -| plug | On means plugged in, Off means unplugged. | -| power | On means power detected, Off means no power. | -| presence | On means home, Off means away. | -| problem | On means problem detected, Off means no problem (OK). | -| safety | On means unsafe, Off means safe. | -| smoke | On means smoke detected, Off means no smoke (clear). | -| sound | On means sound detected, Off means no sound (clear). | -| vibration | On means vibration detected, Off means no vibration. | -| window | On means open, Off means closed. | \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_climate.md b/website/translated_docs/no-NO/entity_climate.md deleted file mode 100644 index 477e1bcd..00000000 --- a/website/translated_docs/no-NO/entity_climate.md +++ /dev/null @@ -1,230 +0,0 @@ ---- -title: Climate Entity -sidebar_label: Climate ---- - -> A climate entity is a device that controls temperature, humidity, or fans, such as A/C systems and humidifiers. Derive entity platforms from [`homeassistant.components.climate.ClimateDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/climate/__init__.py) - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------------------- | ---------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | -| current_fan_mode | string | None | Returns the current fan mode. | -| current_hold_mode | string | None | The current hold mode, e.g., home, away, temp. | -| current_humidity | float | None | The current humidity. | -| current_operation | string | None | The current operation (e.g. heat, cool, idle). Used to determine `state`. | -| current_swing_mode | string | None | Returns the fan setting. | -| current_temperature | float | None | The current temperature. | -| fan_list | list | None | Returns the list of available fan modes. | -| is_aux_heat_on | bool | None | Returns True if an auxiliary heater is on. | -| is_away_mode_on | bool | None | Return true if away mode is on. | -| is_on | bool | None | Returns True if device is on. Used to determine `state`. | -| max_humidity | int | `DEFAULT_MAX_HUMIDITY` (value == 99) | Returns the maximum humidity. | -| max_temp | int | `DEFAULT_MAX_TEMP` (value == 35) | Returns the maximum temperature. | -| min_humidity | int | `DEFAULT_MIN_HUMIDITY` (value == 30) | Returns the minimum humidity. | -| min_temp | int | `DEFAULT_MIN_TEMP` (value == 7) | Returns the minimum temperature. | -| operation_list | list | None | List of available operation modes. | -| precision | float | PRECISION_WHOLE | The precision of the temperature in the system: tenths for TEMP_CELSIUS, whole number otherwise. | -| state | string | None | Returns the current state. | -| state_attributes | dictionary | N/A | The optional state attributes: current temperature, minimum temperature, maximum temperature, and target temperature. | -| supported_features | list | `NotImplementedError()` | Returns list of supported features. | -| swing_list | list | None | Returns the list of available swing modes. | -| target_humidity | float | None | The target humidity. | -| target_temperature | float | None | The temperature currently set to be reached. | -| target_temperature_high | float | None | The upper bound target temperature | -| target_temperature_low | float | None | The lower bound target temperature | -| target_temperature_step | float | None | The supported step of target temperature | -| temperature_unit | string | `NotImplementedError` | The unit of temperature measurement for the system (e.g. Celsius). | - -### States - -| Name | Description | -| ---------------- | ------------------------------ | -| STATE_HEAT | The device is set to heat. | -| STATE_COOL | The device is set to cool. | -| STATE_IDLE | The device is idle. | -| STATE_AUTO | The device is set to auto. | -| STATE_MANUAL | The device is set to manual. | -| STATE_DRY | The device is set to dry. | -| STATE_FAN_ONLY | The device is set to fan-only. | -| STATE_ECO | The device is set to eco-mode. | - -### Supported features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Name | Description | -| --------------------------------- | ------------------------------------------------------ | -| SUPPORT_TARGET_TEMPERATURE | The device supports a target temperature. | -| SUPPORT_TARGET_TEMPERATURE_HIGH | The device supports an upper bound target temperature. | -| SUPPORT_TARGET_TEMPERATURE_LOW | The device supports a lower bound target temperature. | -| SUPPORT_TARGET_HUMIDITY | The device supports a target humidity. | -| SUPPORT_TARGET_HUMIDITY_HIGH | The device supports an upper bound target humidity. | -| SUPPORT_TARGET_HUMIDITY_LOW | The device supports a lower bound target humidity. | -| SUPPORT_FAN_MODE | The device supports fan modes. | -| SUPPORT_OPERATION_MODE | The device supports operation modes. | -| SUPPORT_HOLD_MODE | The device supports hold modes. | -| SUPPORT_SWING_MODE | The device supports swing modes. | -| SUPPORT_AWAY_MODE | The device supports away mode. | -| SUPPORT_AUX_HEAT | The device supports auxiliary heaters. | -| SUPPORT_ON_OFF | The device supports on/off states. | - -## Methods - -### Set fan mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_fan_mode(self, fan_mode): - """Set new target fan mode.""" - - async def async_set_fan_mode(self, fan_mode): - """Set new target fan mode.""" -``` - -### Set hold mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_hold_mode(self, hold_mode): - """Set new target hold mode.""" - - async def async_set_hold_mode(self, hold_mode): - """Set new target hold mode.""" -``` - -### Set humidity - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_humidity(self, humidity): - """Set new target humidity.""" - - async def async_set_humidity(self, humidity): - """Set new target humidity.""" -``` - -### Set operation mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_operation_mode(self, operation_mode): - """Set new target operation mode.""" - - async def async_set_operation_mode(self, operation_mode): - """Set new target operation mode.""" -``` - -### Set swing mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_swing_mode(self, swing_mode): - """Set new target swing operation.""" - - async def async_set_swing_mode(self, swing_mode): - """Set new target swing operation.""" -``` - -### Set temperature - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_temperature(self, **kwargs): - """Set new target temperature.""" - - async def async_set_temperature(self, **kwargs): - """Set new target temperature.""" -``` - -### Turn auxiliary heater on - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_aux_heat_on(self): - """Turn auxiliary heater on.""" - - async def async_turn_aux_heat_on(self): - """Turn auxiliary heater on.""" -``` - -### Turn auxiliary heater off - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_aux_heat_off(self): - """Turn auxiliary heater off.""" - - async def async_turn_aux_heat_off(self): - """Turn auxiliary heater off.""" -``` - -### Turn away mode on - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_away_mode_on(self): - """Turn away mode on.""" - - async def async_turn_away_mode_on(self): - """Turn away mode on.""" -``` - -### Turn away mode off - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_away_mode_off(self): - """Turn away mode off.""" - - async def async_turn_away_mode_off(self): - """Turn away mode off.""" -``` - -### Turn the device on - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_on(self): - """Turn device on.""" - - async def async_turn_on(self): - """Turn device on.""" -``` - -### Turn the device off - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_off(self): - """Turn device off.""" - - async def async_turn_off(self): - """Turn device off.""" -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_cover.md b/website/translated_docs/no-NO/entity_cover.md deleted file mode 100644 index 9fe8a9ce..00000000 --- a/website/translated_docs/no-NO/entity_cover.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: Cover Entity -sidebar_label: Cover ---- - -A cover entity is a device that controls an opening or cover, such as a garage door and window shade. Derive entity platforms from [`homeassistant.components.cover.CoverDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/cover/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -### Platform Properties (to be implemented by deriving platform classes) - -| Name | Type | Default | Description | -| ----------------------------- | ---- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| current_cover_position | int | None | The current position of cover where 0 means closed and 100 is fully open. Required with `SUPPORT_SET_POSITION`. | -| current_cover_tilt_position | int | None | The current tilt position of the cover where 0 means closed/no tilt and 100 means open/maximum tilt. Required with `SUPPORT_SET_TILT_POSITION` | -| is_opening | bool | None | If the cover is opening or not. Used to determine `state`. | -| is_closing | bool | None | If the cover is closing or not. Used to determine `state`. | -| is_closed | bool | `NotImplementedError()` | If the cover is closed or not. if the state is unknown, return `None`. Used to determine `state`. | - -### Entity Properties (base class properties which may be overriden) - -| Name | Type | Default | Description | -| ------------------ | ------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | -| device_class | string | None | Describes the type/class of the cover. Must be `None` or one of the valid values from the table below. | -| supported_features | int (bitwise) | Value determined from `current_cover_position` and `current_cover_tilt_position` | Describes the supported features. See the related table below for details. | - -### Device Classes - -| Constant | Description | -| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `DEVICE_CLASS_AWNING` | Control of an awning, such as an exterior retractible window, door, or patio cover. | -| `DEVICE_CLASS_BLIND` | Control of blinds, which are linked slats that expand or collapse to cover an opening or may be tilted to partially cover an opening, such as window blinds. | -| `DEVICE_CLASS_CURTAIN` | Control of curtains or drapes, which is often fabric hung above a window or door that can be drawn open. | -| `DEVICE_CLASS_DAMPER` | Control of a mechanical damper that reduces air flow, sound, or light. | -| `DEVICE_CLASS_DOOR` | Control of a door or gate that provides access to an area. | -| `DEVICE_CLASS_GARAGE` | Control of a garage door that provides access to a garage. | -| `DEVICE_CLASS_SHADE` | Control of shades, which are a continous plane of material or connected cells that expanded or collapsed over an opening, such as window shades. | -| `DEVICE_CLASS_SHUTTER` | Control of shutters, which are linked slats that swing out/in to cover an opening or may be tilted to partially cover an opening, such as indoor or exterior window shutters. | -| `DEVICE_CLASS_WINDOW` | Control of a physical window that opens and closes or may tilt. | - -### States - -| Constant | Description | -| --------------- | --------------------------------------------------------------- | -| `STATE_OPENING` | The cover is in the process of opening to reach a set position. | -| `STATE_OPEN` | The cover has reached the open position. | -| `STATE_CLOSING` | The cover is in the process of closing to reach a set position. | -| `STATE_CLOSED` | The cover has reach the closed position. | - -### Supported Features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Constant | Description | -| --------------------------- | -------------------------------------------------------------------------------- | -| `SUPPORT_OPEN` | The cover supports being opened. | -| `SUPPORT_CLOSE` | The cover supports being closed. | -| `SUPPORT_SET_POSITION` | The cover supports moving to a specific position between opened and closed. | -| `SUPPORT_STOP` | The cover supports stopping the current action (open, close, set position) | -| `SUPPORT_OPEN_TILT` | The cover supports being tilting open. | -| `SUPPORT_CLOSE_TILT` | The cover supports being tilting closed. | -| `SUPPORT_SET_TILT_POSITION` | The cover supports moving to a specific tilt position between opened and closed. | -| `SUPPORT_STOP_TILT` | The cover supports stopping the current tilt action (open, close, set position) | - -## Methods - -### Open cover - -Only implement this method if the flag `SUPPORT_CLOSE` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover(self, **kwargs): - """Open the cover.""" - - async def async_open_cover(self, **kwargs): - """Open the cover.""" -``` - -### Close cover - -Only implement this method if the flag `SUPPORT_CLOSE` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover(self, **kwargs): - """Close cover.""" - - async def async_close_cover(self, **kwargs): - """Close cover.""" -``` - -### Set cover position - -Only implement this method if the flag `SUPPORT_SET_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" - - async def async_set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" - -``` - -### Stop cover - -Only implement this metohd if the flag `SUPPORT_STOP` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover(self, **kwargs): - """Stop the cover.""" -``` - -### Open cover tilt - -Only implement this method if the flag `SUPPORT_OPEN_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" - - async def async_open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" -``` - -### Close cover tilt - -Only implement this method if the flag `SUPPORT_CLOSE_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" - - async def async_close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" -``` - -### Set cover tilt position - -Only implement this method if the flag `SUPPORT_SET_TILT_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" - - async def async_set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" -``` - -### Stop cover tilt - -Only implement this method if the flag `SUPPORT_STOP_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover_tilt(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover_tilt(self, **kwargs): - """Stop the cover.""" -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_fan.md b/website/translated_docs/no-NO/entity_fan.md deleted file mode 100644 index 27b6f7dc..00000000 --- a/website/translated_docs/no-NO/entity_fan.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Fan Entity -sidebar_label: Fan ---- - -A fan entity is a device that controls the different vectors of your fan such as speed, direction and oscillation. Derive enitity platforms from ['homeassistant.components.fan.FanDevice'](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/fan/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------------ | ------- | ------- | --------------------------------------- | -| current_direction | str | None | Return the current direction of the fan | -| is_on | boolean | None | Return true if the entity is on | -| speed | str | None | Return the current speed | -| speed_list | list | None | Get the list of available speeds | -| state_attributes | dict | None | Return optional state attributes | -| supported_features | int | None | Flag supported features | - -## Supported Features - -| Constant | Description | -| --------------------- | ---------------------------------------------- | -| 'SUPPORT_DIRECTION' | The fan supports changing the direction of it. | -| 'SUPPORT_SET_SPEED' | The fan supports setting the speed. | -| 'SUPPORT_OSCILLATE' | The fan supports oscillation. | - -## Methods - -### Set direction - -Only implement this method if the flag `SUPPORT_DIRECTION` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def set_direction(self, direction: str) -> None: - """Set the direction of the fan.""" - - async def async_set_direction(self, direction: str): - """Set the direction of the fan.""" -``` - -### Set speed - -Only implement this method if the flag `SUPPORT_SET_SPEED` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def set_speed(self, speed: str) -> None: - """Set the speed of the fan.""" - - async def async_set_speed(self, speed: str): - """Set the speed of the fan.""" -``` - -### Turn on - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def turn_on(self, speed: str = None, **kwargs) -> None: - """Turn on the fan.""" - - async def async_turn_on(self, speed: str = None, **kwargs): - """Turn on the fan.""" -``` - -### Oscillate - -Only implement this method if the flag `SUPPORT_OSCILLATE` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def oscillate(self, oscillating: bool) -> None: - """Oscillate the fan.""" - - def async_oscillate(self, oscillating: bool): - """Oscillate the fan.""" -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_index.md b/website/translated_docs/no-NO/entity_index.md deleted file mode 100644 index 5385e078..00000000 --- a/website/translated_docs/no-NO/entity_index.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Entity -sidebar_label: Introduction ---- - -Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating. - -Below is an example switch entity that keeps track of their state in memory. - -```python -from homeassistant.components.switch import SwitchDevice - -class MySwitch(SwitchDevice): - - def __init__(self): - self._is_on = False - - @property - def name(self): - """Name of the device.""" - return 'My Switch' - - @property - def is_on(self): - """If the switch is currently on or off.""" - return self._is_on - - def turn_on(self, **kwargs): - """Turn the switch on.""" - self._is_on = True - - def turn_off(self, **kwargs): - """Turn the switch off.""" - self._is_on = False -``` - -That's all there is to it to build a switch entity! Continue reading to learn more or check out the [video tutorial](https://youtu.be/Cfasc9EgbMU?t=737). - -## Updating the entity - -An entity represents a device. There are various strategies to keep your entity in sync with the state of the device, the most popular one being polling. - -### Polling - -With polling, Home Assistant will ask the entity from time to time (depending on the update interval of the component) to fetch the latest state. Home Assistant will poll an entity when the `should_poll` property returns `True` (the default value). You can either implement your update logic using `update()` or the async method `async_update()`. This method should fetch the latest state from the device and store it in an instance variable for the properties to return it. - -### Subscribing to updates - -When you subscribe to updates, your code is responsible for letting Home Assistant know that an update is available. Make sure you have the `should_poll` property return `False`. - -Whenever you receive new state from your subscription, you can tell Home Assistant that an update is available by calling `schedule_update_ha_state()` or async callback `async_schedule_update_ha_state()`. Pass in the boolean `True` to the method if you want Home Assistant to call your update method before writing the update to Home Assistant. - -## Generic properties - -The entity base class has a few properties that are common among all entities in Home Assistant. These can be added to any entity regardless of the type. All these properties are optional and don't need to be implemented. - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| assumed_state | boolean | `False` | Return `True` if the state is based on our assumption instead of reading it from the device. | -| available | boolean | `True` | Indicate if Home Assistant is able to read the state and control the underlying device. | -| device_state_attributes | dict | `None` | Extra information to store in the state machine. It needs to be information that further explains the state, it should not be static information like firmware version. See [below](entity_index.md#standard_attributes) for details of standard attributes. | -| entity_picture | URL | `None` | Url of a picture to show for the entity. | -| name | string | `None` | Name of the entity | -| should_poll | boolean | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](#methods). | -| unique_id | string | `None` | A unique identifier for this entity. Needs to be unique within a platform (ie `light.hue`). Should not be configurable by the user or be changeable. [Learn more.](entity_registry_index.md#unique-id-requirements) | - -## Advanced properties - -The following properties are also available on entities. However, they are for advanced use only and should be used with caution. - -| Name | Type | Default | Description | -| ------------ | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| force_update | boolean | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine. | -| hidden | boolean | `False` | Indicate if the entity should not be shown on the frontend. | -| icon | icon | `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all devices. | - -## Standard attributes - -The following `device_state_attributes` are considered standard and should follow the convention below. The constant should be imported from `homeassistant/const.py`. - -| Name | Type | Unit | Constant | Description | -| ---------------- | ------- | ---- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| battery_charging | boolean | N/A | `ATTR_BATTERY_CHARGING` | Battery charging status of the entity, shown as a boolean `true` or `false`. If charging is not supported, then this attribute should not be created. | -| battery_level | integer | % | `ATTR_BATTERY_LEVEL` | Battery level of the entity, shown as an integer percentage between 0-100. | - -## Lifecycle hooks - -Use these lifecycle hooks to execute code when certain events happen to the entity. All lifecycle hooks are async methods. - -### `async_added_to_hass()` - -Called when an entity has their entity_id and hass object assigned, before it is written to the state machine for the first time. Example uses: restore the state, subscribe to updates or set callback/dispatch function/listener. - -### `async_will_remove_from_hass()` - -Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates. - -## Changing the entity model - -If you want to add a new feature to an entity or any of its subtypes (light, switch, etc), you will need to propose it first in our [architecture repo](https://github.com/home-assistant/architecture/issues). Only additions will be considered that are common features among various vendors. \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_light.md b/website/translated_docs/no-NO/entity_light.md deleted file mode 100644 index 1b3d6561..00000000 --- a/website/translated_docs/no-NO/entity_light.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Light Entity -sidebar_label: Light ---- - - -A light entity is a device that controls the brightness, RGB value,color temperature and effects of a light source. - -## Properties - -| Name | Type | Default | Description | -| ------------------ | ------ | ------- | --------------------------------------------------------- | -| brightness | int | None | Return the brightness of this light between 0..255 | -| color_temp | int | None | Return the CT color value in mireds. | -| effect | String | None | Return the current effect. | -| effect_list | list | None | Return the list of supported effects. | -| hs_color | list | None | Return the hue and saturation color value [float, float]. | -| is_on | bool | bool | Returns if the light entity is on or not. | -| max_minreds | int | int | Return the warmest color_temp that this light supports. | -| min_mireds | int | int | Return the coldest color_temp that this light supports. | -| supported_features | int | int | Flag supported features. | -| white_value | int | None | Return the white value of this light between 0..255. | - -## Support Feature - -| Constant | Description | -| --------------------- | --------------------------------------------------------------------- | -| `SUPPORT_BRIGHTNESS` | Controls the brightness of a light source | -| `SUPPORT_COLOR` | Controls the color a light source shows | -| `SUPPORT_COLOR_TEMP` | Controls the representation a light source shows based on temperature | -| `SUPPORT_EFFECT` | Controls the effect a light source shows | -| `SUPPORT_FLASH` | Controls the duration of a flash a light source shows | -| `SUPPORT_TRANSITION` | Controls the duration of transitions between color and effects | -| `SUPPORT_WHITE_VALUE` | Controls the white light a light source shows. | - -## Methods - -# Turn on Light Device - -```python -class MyLightDevice(LightDevice): - def turn_on(self, **kwargs): - """Turn the device on.""" - - async def async_turn_on(self, **kwargs): - """Turn device on.""" - -``` - -# Turn Off Light Device - -```python -class MyLightDevice(LightDevice): - - def turn_off(self, **kwargs): - """Turn the device off.""" - - async def async_turn_off(self, **kwargs): - """Turn device off.""" - -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_lock.md b/website/translated_docs/no-NO/entity_lock.md deleted file mode 100644 index 7983db21..00000000 --- a/website/translated_docs/no-NO/entity_lock.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Lock Entity -sidebar_label: Lock ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ---- | ---- | ------- | ----------- | -| | | | | - -## Methods \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_media_player.md b/website/translated_docs/no-NO/entity_media_player.md deleted file mode 100644 index ab327f05..00000000 --- a/website/translated_docs/no-NO/entity_media_player.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Media Player Entity -sidebar_label: Media Player ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| --------------------------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------- | -| sound_mode | string | None | The current sound mode of the media player | -| sound_mode_list | list | None | Dynamic list of available sound modes (set by platform, empty means sound mode not supported) | -| source | string | None | The currently selected input source for the media player. | -| source_list | list | None | The list of possible input sources for the media player. (This list should contain human readable names, suitible for frontend display) | -| media_image_url | string | None | URL that represents the current image. | -| media_image_remotely_accessible | boolean | False | Return `True` if property `media_image_url` is accessible outside of the home network. | -| device_class | string | `None` | Type of binary sensor. | - -## Methods - -### Select sound mode - -Optional. Switch the sound mode of the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - def async_select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - -### Select source - -Optional. Switch the selected input source for the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_source(self, source): - """Select input source.""" - - def async_select_source(self, source): - """Select input source.""" - - -### Mediatype - -Required. Returns one of the defined constants from the below list that matches the mediatype - -| CONST | -| --------------------- | -| MEDIA_TYPE_MUSIC | -| MEDIA_TYPE_TVSHOW | -| MEDIA_TYPE_MOVIE | -| MEDIA_TYPE_VIDEO | -| MEDIA_TYPE_EPISODE | -| MEDIA_TYPE_CHANNEL | -| MEDIA_TYPE_PLAYLIST | -| MEDIA_TYPE_IMAGE | -| MEDIA_TYPE_URL | -| MEDIA_TYPE_GAME | -| MEDIA_TYPE_APP | - - class MyMediaPlayer(MediaPlayerDevice): - # Implement the following method. - - def media_content_type(self): - """Content type of current playing media.""" - - -### Available device classes - -Optional. What type of media device is this. It will possibly map to google device types. - -| Value | Description | -| ------- | ----------------------------------------- | -| tv | Device is a television type device. | -| speaker | Device is speakers or stereo type device. | \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_registry_index.md b/website/translated_docs/no-NO/entity_registry_index.md deleted file mode 100644 index aa346829..00000000 --- a/website/translated_docs/no-NO/entity_registry_index.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Entity Registry -sidebar_label: Introduction ---- - -The entity registry is a registry where Home Assistant keeps track of entities. Any entity that is added to Home Assistant and has a unique ID will be registered in the registry. - -Being registered has the advantage that the same entity will always get the same entity ID. It will also prevent other entities from using that entity ID. - -A user is also able to override the name of an entity in the entity registry. When set, the name of the entity registry is used in favor of the name the device might give itself. - -## Unique ID requirements - -An entity is looked up in the registry based on a combination of the plaform type (e.g., `light`), and the integration name (domain) (ie hue) and the unique ID of the entity. It is therefore very important that the unique ID is unique! It is also important that it is not possible for the user to change the unique ID, because that means it will lose all its settings related to it. - -Good sources for a unique ID: - -- Serial number of a device -- MAC address of a device -- latitude/longitude - -If a device has a single serial but provides multiple entities, combine the serial with unique identifiers for the entities. For example, if a device measures both temperature and humidity, you can uniquely identify the entities using `{serial}-{sensor_type}`. \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_remote.md b/website/translated_docs/no-NO/entity_remote.md deleted file mode 100644 index b4a0251d..00000000 --- a/website/translated_docs/no-NO/entity_remote.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Remote Entity -sidebar_label: Remote ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ---- | ---- | ------- | ----------- | -| | | | | - -## Methods \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_sensor.md b/website/translated_docs/no-NO/entity_sensor.md deleted file mode 100644 index 6a7e6307..00000000 --- a/website/translated_docs/no-NO/entity_sensor.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Sensor Entity -sidebar_label: Sensor ---- - -A sensor is a read-only entity that provides some information. Information has a value and optionally, a unit of measurement. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| --------------------- | ------ | ------------ | -------------------------------------------------------- | -| state | string | **Required** | The value of the sensor. | -| unit_of_measurement | string | `None` | The unit of measurement that the sensor is expressed in. | -| device_class | string | `None` | Type of sensor. | - -### Available device classes - -If specifying a device class, your sensor entity will need to also return the correct unit of measurement. - -| Type | Unit | Description | -| --------------- | -------- | -------------------------- | -| battery | % | % of battery that is left. | -| humidity | % | % of humidity in the air. | -| illuminance | lx/lm | Light level. | -| signal_strength | dB/dBm | Signal strength. | -| temperature | °C/°F | Temperature. | -| timestamp | ISO8601 | Timestamp. | -| power | W,kW | Power. | -| pressure | hPa,mbar | Pressure. | \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_switch.md b/website/translated_docs/no-NO/entity_switch.md deleted file mode 100644 index 14039422..00000000 --- a/website/translated_docs/no-NO/entity_switch.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Switch Entity -sidebar_label: Switch ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------------ | ------- | ------------ | ----------------------------------------------------------------------- | -| is_on | boolean | **Required** | If the switch is currently on or off. | -| current_power_w | float | `None` | The current power usage in W. | -| today_energy_kwh | float | `None` | Total energy usage in kWh. | -| is_standby | boolean | `None` | Indicate if the device connected to the switch is currently in standby. | - -## Methods - -### Turn On - -Turn the switch on. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def turn_on(self, **kwargs) -> None: - """Turn the entity on.""" - - async def async_turn_on(self, **kwargs): - """Turn the entity on.""" - -``` - -### Turn Off - -Turn the switch off. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def turn_off(self, **kwargs): - """Turn the entity off.""" - - async def async_turn_off(self, **kwargs): - """Turn the entity off.""" -``` - -### Toggle - -Optional. If not implemented will default to checking what method to call using the `is_on` property. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def toggle(self, **kwargs): - """Toggle the entity.""" - - async def async_toggle(self, **kwargs): - """Toggle the entity.""" -``` - -### Available device classes - -Optional. What type of device this. It will possibly map to google device types. - -| Value | Description | -| ------ | ----------------------------------------- | -| outlet | Device is an outlet for power. | -| switch | Device is switch for some type of entity. | \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_vacuum.md b/website/translated_docs/no-NO/entity_vacuum.md deleted file mode 100644 index b947d3df..00000000 --- a/website/translated_docs/no-NO/entity_vacuum.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Vacuum Entity -sidebar_label: Vacuum ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| -------------------- | ------ | ------------------------------- | --------------------------------------------------- | -| name | string | **Required** | Name of the device. | -| state | string | **Required** | One of the states listed in the states section. | -| battery_level | int | `none` | Current battery level. | -| battery_icon | string | function | Battery icon to show in UI. | -| cleaning_mode | string | `none` | The current cleaning mode. | -| cleaning_mode_list | list | `NotImplementedError()` | List of available fan speeds and cleaning modes. | -| error | string | **Required** with `STATE_ERROR` | An error message if the vacuum is in `STATE_ERROR`. | - -## States - -| State | Description | -| ----------------- | ------------------------------------------------------------------------------------------------------- | -| `STATE_CLEANING` | The vacuum is currently cleaning. | -| `STATE_DOCKED` | The vacuum is currently docked, it is assumed that docked can also mean charging. | -| `STATE_PAUSED` | The vacuum was cleaning but was paused without returning to the dock. | -| `STATE_IDLE` | The vacuum is not paused, not docked and does not have any errors. | -| `STATE_RETURNING` | The vacuum is done cleaning and is currently returning to the dock, but not yet docked. | -| `STATE_ERROR` | The vacuum encountered an error while cleaning, the error can be specified as a property on the entity. | - -## Methods - -### `turn_on` or `async_turn_on` - -Turn the vacuum on and start cleaning. - -### `turn_off`or `async_turn_off` - -Turn the vacuum off stopping the cleaning and returning home. - -### `return_to_base` or `async_return_to_base` - -Set the vacuum cleaner to return to the dock. - -### `stop` or `async_stop` - -Stop the vacuum cleaner, do not return to base. - -### `clean_spot` or `async_clean_spot` - -Perform a spot clean-up. - -### `locate` or `async_locate` - -Locate the vacuum cleaner. - -### `set_cleaning_mode` or `async_set_cleaning_mode` - -Set the cleaning mode. - -### `send_command` or `async_send_command` - -Send a command to a vacuum cleaner. \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_water_heater.md b/website/translated_docs/no-NO/entity_water_heater.md deleted file mode 100644 index b4a13e29..00000000 --- a/website/translated_docs/no-NO/entity_water_heater.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: Water Heater Entity -sidebar_label: Water Heater ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| -------------- | ------ | ------- | ------------------------------------------ | -| min_temp | float | 110°F | The minimum temperature that can be set. | -| max_temp | float | 140°F | The maximum temperature that can be set. | -| temperature | float | none | The current temperature in °C or °F. | -| operation_mode | string | none | The current operation mode. | -| operation_list | list | none | List of possible operation modes. | -| away_mode | string | none | The current status of away mode. (on, off) | - -The allowed operation modes are specified in the base component and implementations of the water_heater component cannot differ. - -Properties have to follow the units defined in the `unit_system`. - -## States - -| State | Description | -| ------------------- | ---------------------------------------------------------------- | -| `STATE_ECO` | Energy efficient mode, provides energy savings and fast heating. | -| `STATE_ELECTRIC` | Electric only mode, uses the most energy. | -| `STATE_PERFORMANCE` | High performance mode. | -| `STATE_HIGH_DEMAND` | Meet high demands when water heater is undersized. | -| `STATE_HEAT_PUMP` | Slowest to heat, but uses less energy. | -| `STATE_GAS` | Gas only mode, uses the most energy. | -| `STATE_OFF` | The water heater is off. | - -## Methods - -### `set_temperature` or `async_set_temperature` - -Sets the temperature the water heater should heat water to. - -### `set_operation_mode`or `async_set_operation_mode` - -Sets the operation mode of the water heater. Must be in the operation_list. - -### `turn_away_mode_on` or `async_turn_away_mode_on` - -Set the water heater to away mode. - -### `turn_away_mode_off` or `async_turn_away_mode_off` - -Set the water heater back to the previous operation mode. Turn off away mode. \ No newline at end of file diff --git a/website/translated_docs/no-NO/entity_weather.md b/website/translated_docs/no-NO/entity_weather.md deleted file mode 100644 index b92ccbe6..00000000 --- a/website/translated_docs/no-NO/entity_weather.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Weather Entity -sidebar_label: Weather ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------ | ------ | ------------ | ----------------------------------------------- | -| state | string | **Required** | The current weather condition. | -| temperature | float | **Required** | The current temperature in °C or °F. | -| pressure | float | `None` | The current air pressure in hPa or inHg. | -| humidity | float | `None` | The current humidity in %. | -| visibility | float | `None` | The current visibility in km or mi. | -| wind_speed | float | `None` | The current wind speed in km/h or mi/h. | -| wind_bearing | string | `None` | The current wind bearing, 1-3 letters. | -| forecast | array | `None` | Daily or Hourly forecast data. | -| attribution | string | `None` | The branding text required by the API provider. | - -Properties have to follow the units defined in the `unit_system`. - -### Forecast - -Forecast data should either be daily or hourly. - -| Name | Type | Default | Description | -| ----------- | ------ | ------------ | --------------------------------------- | -| datetime | string | **Required** | UTC Date time in RFC 3339 format. | -| temperature | float | **Required** | The higher temperature in °C or °F | -| condition | string | `None` | The weather condition at this point. | -| templow | float | `None` | The lower daily Temperature in °C or °F | - -### Recommended values for state and condition - -These weather conditions are included in our translation files and also show the corresponding icon. - -| Condition | Description | -| --------------- | --------------------------------- | -| clear-night | Clear night | -| cloudy | Many clouds | -| fog | Fog | -| lightning | Lightning/ thunderstorms | -| lightning-rainy | Lightning/ thunderstorms and rain | -| partlycloudy | A few clouds | -| pouring | Pouring rain | -| rainy | Rain | -| snowy | Snow | -| snowy-rainy | Snow and Rain | -| sunny | Sunshine | -| windy | Wind | -| windy-variant | Wind and clouds | - -This means that the `weather` platforms don't need to support languages. \ No newline at end of file diff --git a/website/translated_docs/no-NO/external_api_rest.md b/website/translated_docs/no-NO/external_api_rest.md deleted file mode 100644 index 965aae96..00000000 --- a/website/translated_docs/no-NO/external_api_rest.md +++ /dev/null @@ -1,530 +0,0 @@ ---- -title: "REST API" ---- - -Home Assistant provides a RESTful API on the same port as the web frontend. (default port is port 8123). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -- http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -- http://IP_ADDRESS:8123/api/ is a RESTful API. - -The API accepts and returns only JSON encoded objects. - -All API calls have to be accompanied by the header `Authorization: Bearer ABCDEFGH`, where `ABCDEFGH` is replaced by your token. You can obtain a token ("Long-Lived Access Token") by logging into the frontend using a web browser, and going to [your profile](https://www.home-assistant.io/docs/authentication/#your-account-profile) `http://IP_ADDRESS:8123/profile`. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```bash -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. - -```python -from requests import get - -url = 'http://localhost:8123/ENDPOINT' -headers = { - 'Authorization': 'Bearer ABCDEFGH', - 'content-type': 'application/json', -} - -response = get(url, headers=headers) -print(response.text) -``` - -Another option is to use the Restful Command component https://www.home-assistant.io/components/rest_command/ in a Home Assistant automation or script. - -```yaml -turn_light_on: - url: http://localhost:8123/api/states/light.study_light - method: POST - headers: - authorization: 'Bearer ABCDEFGH' - content-type: 'application/json' - payload: '{"state":"on"}' -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on one or more entities - comma separated. -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates the current state of an entity. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance. - - -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/external_api_rest_python.md b/website/translated_docs/no-NO/external_api_rest_python.md deleted file mode 100644 index 3d415b76..00000000 --- a/website/translated_docs/no-NO/external_api_rest_python.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: "REST API - Python bindings" ---- - -This API is deprecated and was removed since Home Assistant 0.77.0 - -More information can be found in this [blog post](../../../blog/2018/08/13/deprecating-remote-package.html). \ No newline at end of file diff --git a/website/translated_docs/no-NO/external_api_server_sent_events.md b/website/translated_docs/no-NO/external_api_server_sent_events.md deleted file mode 100644 index 676494c3..00000000 --- a/website/translated_docs/no-NO/external_api_server_sent_events.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: "Server-sent events" ---- - -The [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) feature is a one-way channel from your Home Assistant server to a client which is acting as a consumer. For a bi-directional streaming API, check out the [WebSocket API](external_api_websocket.md). - -The URI that is generating the data is `/api/stream`. - -A requirement on the client-side is existing support for the [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) interface. - -There are various ways to access the stream. If you have not set an `api_password` in the [`http`](https://www.home-assistant.io/components/http/) section of your `configuration.yaml` file then you use your modern browser to read the messages. A command-line option is `curl`: - -```bash -$ curl -X GET -H 'Authorization: Bearer ABCDEFGH' \ - -H "Content-Type: application/json" http://localhost:8123/api/stream -``` - -> Will no longer work with the new Authentication system. - -You can create a convenient view for this by creating an HTML file (`sse.html`) in the `www` folder of your Home Assistant configuration directory (`.homeassistant`). Paste this snippet into the file: - -```html - - - -

Getting Home Assistant server events

-
- - - -``` - -Visit to see the stream of events. - -## Examples - -A simple way to consume server-sent events is to use a command-line http client like [httpie](https://httpie.org/). Installation info is on the site (if you use Homebrew, it's `brew install httpie`). Once installed, run this snippet from your terminal: - -```bash -$ http --stream http://localhost:8123/api/stream 'Authorization:Bearer ABCDEFGH' content-type:application/json -``` - -### Website - -> Will no longer work with the new Authentication system. - -The [home-assistant-sse](https://github.com/fabaff/home-assistant-sse) repository contains a more advanced example. - -### Python - -If you want to test the server-sent events without creating a website, the Python module [`sseclient` ](https://pypi.python.org/pypi/sseclient/) can help. To install (assuming Python and pip3 are already installed): - -```bash -$ pip3 install sseclient -``` - -A simple script to consume SSE in Python looks like this: - -```python -from sseclient import SSEClient - -auth = {'Authorization': 'Bearer ABCDEFGH'} -messages = SSEClient('http://localhost:8123/api/stream', headers=auth) - -for msg in messages: - print(msg) -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/external_api_websocket.md b/website/translated_docs/no-NO/external_api_websocket.md deleted file mode 100644 index f194c309..00000000 --- a/website/translated_docs/no-NO/external_api_websocket.md +++ /dev/null @@ -1,434 +0,0 @@ ---- -title: "WebSocket API" ---- - -Home Assistant contains a WebSocket API. This API can be used to stream information from a Home Assistant instance to any client that implements WebSockets. Implementations in different languages: - -- [JavaScript](https://github.com/home-assistant/home-assistant-js-websocket) - powers the frontend -- [Python](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket-client.py) - CLI client using [`asyncws`](https://async-websockets.readthedocs.io/en/latest/) -- [JavaScript/HTML](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket.html) - WebSocket connection in your browser - -Connect your websocket implementation to `ws://localhost:8123/api/websocket`. You will need a valid access token. - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`websocket_api` component](https://www.home-assistant.io/components/websocket_api/) to your `configuration.yaml` file to use the WebSocket API. - -## Server states - -1. Client connects. -2. Authentication phase starts. - - Server sends `auth_required` message. - - Client sends `auth` message. - - If `auth` message correct: go to 3. - - Server sends `auth_invalid`. Go to 6. -3. Send `auth_ok` message -4. Authentication phase ends. -5. Command phase starts. - 1. Client can send commands. - 2. Server can send results of previous commands. -6. Client or server disconnects session. - -During the command phase, the client attaches a unique identifier to each message. The server will add this identifier to each message so that the client can link each message to its origin. - -## Message format - -Each API message is a JSON serialized object containing a `type` key. After the authentication phase messages also must contain an `id`, an integer that contains the number of interactions. - -Example of an auth message: - -```json -{ - "type": "auth", - "access_token": "ABCDEFGHIJKLMNOPQ" -} -``` - -```json -{ - "id": 5, - "type":"event", - "event":{ - "data":{}, - "event_type":"test_event", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -## Authentication phase - -When a client connects to the server, the server will test if the client is authenticated. Authentication will not be necessary if no api_password is set or if the user fulfills one of the other criteria for authentication (trusted network, password in url/header). - -If no authentication is needed, the authentication phase will complete and the server will send an `auth_ok` message. - -```json -{ - "type": "auth_ok" -} -``` - -If authentication is necessary, the server sends out `auth_required`. - -```json -{ - "type": "auth_required" -} -``` - -This means that the next message from the client should be an auth message. You can authorize with an access token. - -```json -{ - "type": "auth", - "access_token": "ABCDEFGH" -} -``` - -For now, we also support authentication with an API password (legacy auth). - -```json -{ - "type": "auth", - "api_password": "supersecret" -} -``` - -If the client supplies valid authentication, the authentication phase will complete by the server sending the `auth_ok` message: - -```json -{ - "type": "auth_ok" -} -``` - -If the data is incorrect, the server will reply with `auth_invalid` message and disconnect the session. - -```json -{ - "type": "auth_invalid", - "message": "Invalid password" -} -``` - -## Command phase - -During this phase the client can give commands to the server. The server will respond to each command with a `result` message indicating when the command is done and if it was successful. - -```json -{ - "id": 6, - "type": "result", - "success": true, - // Can contain extra result info - "result": null -} -``` - -## Subscribe to events - -The command `subscribe_events` will subscribe your client to the event bus. You can either listen to all events or to a specific event type. If you want to listen to multiple event types, you will have to send multiple `subscribe_events` commands. - -```json -{ - "id": 18, - "type": "subscribe_events", - // Optional - "event_type": "state_changed" -} -``` - -The server will respond with a result message to indicate that the subscription is active. - -```json -{ - "id": 18, - "type": "result", - "success": true, - "result": null -} -``` - -For each event that matches, the server will send a message of type `event`. The `id` in the message will point at the original `id` of the `listen_event` command. - -```json -{ - "id": 18, - "type":"event", - "event":{ - "data":{ - "entity_id":"light.bed_light", - "new_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:24.265390+00:00", - "state":"on", - "attributes":{ - "rgb_color":[ - 254, - 208, - 0 - ], - "color_temp":380, - "supported_features":147, - "xy_color":[ - 0.5, - 0.5 - ], - "brightness":180, - "white_value":200, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:24.265390+00:00" - }, - "old_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:10.466994+00:00", - "state":"off", - "attributes":{ - "supported_features":147, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:10.466994+00:00" - } - }, - "event_type":"state_changed", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -### Unsubscribing from events - -You can unsubscribe from previously created subscription events. Pass the id of the original subscription command as value to the subscription field. - -```json -{ - "id": 19, - "type": "unsubscribe_events", - "subscription": 18 -} -``` - -The server will respond with a result message to indicate that unsubscribing was successful. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": null -} -``` - -## Calling a service - -This will call a service in Home Assistant. Right now there is no return value. The client can listen to `state_changed` events if it is interested in changed entities as a result of a service call. - -```json -{ - "id": 24, - "type": "call_service", - "domain": "light", - "service": "turn_on", - // Optional - "service_data": { - "entity_id": "light.kitchen" - } -} -``` - -The server will indicate with a message indicating that the service is done executing. - -```json -{ - "id": 24, - "type": "result", - "success": true, - "result": null -} -``` - -## Fetching states - -This will get a dump of all the current states in Home Assistant. - -```json -{ - "id": 19, - "type": "get_states" -} -``` - -The server will respond with a result message containing the states. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -## Fetching config - -This will get a dump of the current config in Home Assistant. - -```json -{ - "id": 19, - "type": "get_config" -} -``` - -The server will respond with a result message containing the config. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -## Fetching services - -This will get a dump of the current services in Home Assistant. - -```json -{ - "id": 19, - "type": "get_services" -} -``` - -The server will respond with a result message containing the services. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -## Fetching panels - -This will get a dump of the current registered panels in Home Assistant. - -```json -{ - "id": 19, - "type": "get_panels" -} -``` - -The server will respond with a result message containing the current registered panels. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -## Fetching camera thumbnails - -*Introduced in Home Assistant 0.69.* - -Return a b64 encoded thumbnail of a camera entity. - -```json -{ - "id": 19, - "type": "camera_thumbnail" -} -``` - -The server will respond with a result message containing the thumbnail. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Fetching media player thumbnails - -*Introduced in Home Assistant 0.69.* - -Fetch a base64 encoded thumbnail picture for a media player. - -```json -{ - "id": 19, - "type": "media_player_thumbnail", - "entity_id": "media_player.living_room" -} -``` - -The server will respond with the image encoded via base64. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Pings and Pongs - -The API supports receiving a ping from the client and returning a pong. This serves as a heartbeat to ensure the connection is still alive: - -```json -{ - "id": 19, - "type": "ping" -} -``` - -The server must send a pong back as quickly as possible, if the connection is still active: - -```json -{ - "id": 19, - "type": "pong" -} -``` - -## Error handling - -If an error occurs, the `success` key in the `result` message will be set to `false`. It will contain an `error` key containing an object with two keys: `code` and `message`. - -| Code | Description | -| ---- | ------------------------------------------------------------------------- | -| 1 | A non-increasing identifier has been supplied. | -| 2 | Received message is not in expected format (voluptuous validation error). | -| 3 | Requested item cannot be found | - -```json -{ - "id": 12, - "type":"result", - "success": false, - "error": { - "code": 2, - "message": "Message incorrectly formatted: expected str for dictionary value @ data['event_type']. Got 100" - } -} -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/frontend_add_card.md b/website/translated_docs/no-NO/frontend_add_card.md deleted file mode 100644 index 5958da27..00000000 --- a/website/translated_docs/no-NO/frontend_add_card.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Adding state card" ---- - -The main interface of Home Assistant is a list of the current entities and their states. For each entity in the system, a state card will be rendered. State cards will show an icon, the name of the entity, when the state has last changed and the current state or a control to interact with it. - -![Cards in the frontend](/img/en/frontend/frontend-cards1.png) - -The different card types can be found [here](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary). - -Sensors, when not grouped, are shown as so-called badges on top of the state cards. - -![Badges in the frontend](/img/en/frontend/frontend-badges.png) - -The different badges are located in the file [`/src/components/entity/ha-state-label-badge.js`](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/components/entity/ha-state-label-badge.js). - -Adding a custom card type can be done with a few simple steps. For this example we will add a new state card for the domain `camera`: - -1. Add `'camera'` to the array `DOMAINS_WITH_CARD` in the file [/common/const.ts](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/common/const.ts). -2. Create the files `state-card-camera.js` in the folder [/state-summary/](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary). -3. Add `import './state-card-camera.js';` to [state-card-content.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/state-summary/state-card-content.js). \ No newline at end of file diff --git a/website/translated_docs/no-NO/frontend_add_more_info.md b/website/translated_docs/no-NO/frontend_add_more_info.md deleted file mode 100644 index 56519938..00000000 --- a/website/translated_docs/no-NO/frontend_add_more_info.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: "Adding more info dialogs" ---- - -Whenever the user taps or clicks on one of the cards, a more info dialog will show. The header of this dialog will be the state card, followed by the history of this entity for the last 24 hours. Below this the more info component is rendered for that entity. The more info component can show more information or allow more ways of control. - -![The more info dialog for a light allows the user to control the color and the brightness.](/img/en/frontend/frontend-more-info-light.png) - -The instructions to add a more info dialog are very similar to adding a new card type. This example will add a new more info component for the domain `camera`: - -1. Add `'camera'` to the array `DOMAINS_WITH_MORE_INFO` in the file [/common/const.ts](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/common/const.ts). -2. Create the files `more-info-camera.js` in the folder [/dialogs/more-info/controls](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/dialogs/more-info/controls). -3. Add `import './more-info-camera.js';` to [/dialogs/more-info/controls/more-info-content.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/dialogs/more-info/controls/more-info-content.js) \ No newline at end of file diff --git a/website/translated_docs/no-NO/frontend_add_websocket_api.md b/website/translated_docs/no-NO/frontend_add_websocket_api.md deleted file mode 100644 index 77e8f5a1..00000000 --- a/website/translated_docs/no-NO/frontend_add_websocket_api.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: "Extending the WebSocket API" ---- - -As a component you might have information that you want to make available to the frontend. For example, the media player will want to make album covers available for the frontend to show. Our frontend is communicating with the backend over the websocket API, which can be extended with custom commands. - -## Registering a command (Python) - -To register a command, you need to have a message type, a message schema and a message handler. Your component does not have to add the websocket API as a dependency. You register your command, and if the user is using the websocket API, the command will be made available. - -### Message Types - -Message types are made up the domain and the message type, separated by a forward slash. In the below example, we're defining `media_player/thumbnail`. - -```python -# The type of the message -WS_TYPE_MEDIA_PLAYER_THUMBNAIL = 'media_player/thumbnail' -``` - -### Message Schema - -The message schema defines what type of data we expect when the message is invoked. It is defined as a voluptuous schema and has to extend the base web socket command schema. - -```python -import voluptuous as vol - -from homeassistant.components import websocket_api -import homeassistant.helpers.config_validation as cv - - -# The schema for the message -SCHEMA_WEBSOCKET_GET_THUMBNAIL = \ - websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({ - 'type': WS_TYPE_MEDIA_PLAYER_THUMBNAIL, - # The entity that we want to retrieve the thumbnail for. - 'entity_id': cv.entity_id - }) -``` - -### Defining a handler - -Message handlers are callback functions that are run inside the event loop. If you want to do I/O or have to wait for your result, create a new function and queue it up using `hass.async_add_job`. This is done so that the websocket API can get back to handling the next message as soon as possible. - -#### Sending a direct response - -If you are defining a command that is querying simple information, you might be able to fulfill the request while the handler is being called by the websocket API. To do this, use `connection.to_write.put_nowait`. - -```python -@callback -def websocket_handle_thumbnail(hass, connection, msg): - """Handle getting a thumbnail.""" - - # We know the answer without having to fetch any information, - # so we send it directly. - connection.to_write.put_nowait(websocket_api.result_message(msg['id'], { - 'thumbnail': 'http://via.placeholder.com/350x150' - })) -``` - -#### Sending a delayed response - -If your command needs to interact with the network, a device or needs to compute information, you will need to queue a job to do the work and send the response. To do this, use `connection.send_message_outside`. - -```python -@callback -def websocket_handle_thumbnail(hass, connection, msg): - """Handle get media player cover command.""" - # Retrieve media player using passed in entity id. - player = hass.data[DOMAIN].get_entity(msg['entity_id']) - - # If the player does not exist, send an error message. - if player is None: - connection.to_write.put_nowait(websocket_api.error_message( - msg['id'], 'entity_not_found', 'Entity not found')) - return - - # Define a function to be enqueued. - async def send_image(): - """Send image.""" - data, content_type = await player.async_get_media_image() - - # No media player thumbnail available - if data is None: - connection.send_message_outside(websocket_api.error_message( - msg['id'], 'thumbnail_fetch_failed', - 'Failed to fetch thumbnail')) - return - - connection.send_message_outside(websocket_api.result_message( - msg['id'], { - 'content_type': content_type, - 'content': base64.b64encode(data).decode('utf-8') - })) - - # Player exist. Queue up a job to send the thumbnail. - hass.async_add_job(send_image()) -``` - -### Registering with the Websocket API - -With all pieces defined, it's time to register the command. This is done inside your setup method. - -```python -async def async_setup(hass, config): - """Setup of your component.""" - hass.components.websocket_api.async_register_command( - WS_TYPE_MEDIA_PLAYER_THUMBNAIL, websocket_handle_thumbnail, - SCHEMA_WEBSOCKET_GET_THUMBNAIL) -``` - -## Calling the command from the frontend (JavaScript) - -With your command defined, it's time to call it from the frontend! This is done using JavaScript. You will need access to the `hass` object which holds the WebSocket connection to the backend. Then just call `hass.connection.sendMessagePromise`. This will return a promise that will resolve if the command succeeds and errors if the command fails. - -```js -hass.connection.sendMessagePromise({ - type: 'media_player/thumbnail', - entity_id: 'media_player.living_room_tv', -}).then( - (resp) => { - console.log('Message success!', resp.result); - }, - (err) => { - console.error('Message failed!', err); - } -); -``` - -If your command is not sending a response, you can use `hass.connection.sendMessage`. \ No newline at end of file diff --git a/website/translated_docs/no-NO/frontend_architecture.md b/website/translated_docs/no-NO/frontend_architecture.md deleted file mode 100644 index b2be6753..00000000 --- a/website/translated_docs/no-NO/frontend_architecture.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: "Home Assistant Frontend Architecture" -sidebar_label: "Architecture" ---- - -The Home Assistant frontend is built using web components. This is a modern web technology allowing us to encapsulate templates, styling and logic into a single file and expose it as an HTML tag in the browser. These components are composable, allowing a very dynamic and powerful foundation of our application. - -## Structure - -The Home Assistant frontend can be broken up in 4 parts: - -### Bootstrap - -File: `src/entrypoints/core.js` - -This is a very tiny script which is the first thing that is loaded on the page. It is responsible for checking for authentication credentials and setting up the websocket connection with the backend. - -The script allows us to start downloading the data while also downloading the rest of the UI in parallel. - -### App shell - -File: `src/entrypoints/app.js` - -This is everything that is required to render the sidebar and handle the routing. - -### Panels - -Folder: `src/panels/` - -Each page in Home Assistant is a panel. Components can register extra panels to be shown to the user. Examples of panels are "states", "map", "logbook" and "history". - -### More info dialog - -Folder: `src/dialogs/more-info` - -This is a dialog that allows users to see more information about an entity and control its state. - -The more info dialog can be triggered from any component in the app by firing a DOM event `hass-more-info` with as detail `{ entityId: 'light.kitchen' }`. - -## Data Flow - -The frontend leverages the [Websocket API](external_api_websocket.md) and the [Rest API](external_api_rest.md) to interact with Home Assistant. - -The data is made available as the `hass` property which is passed down to every component. The `hass` property contains the whole application state and has methods to call APIs. - -We use a unidirectional data flow (like Flux, Redux). When you make a change in the backend (like turning on a light), the `hass` object will be updated at the root of the application and will be made available to every component that needs it. - -## Routing - -The frontend uses decentralized routing. Each component only knows enough about the routing to know how to handle the part it's responsible for. Further routing is passed down the component tree. - -For example, the `` main component will look at the first part of the url to decide which panel should be loaded. Each panel can have its own mapping between the url and what content to show. - -For the routing, we use the [``](https://www.polymer-project.org/blog/routing) web component. - -## Bundling - -We use Webpack to bundle up the application. We have various gulp scripts to help with generating the icon set and the index.html. - -We're aggresively code splitting our application by leveraging the dynamic import syntax (`import('path/to/some/file.js')`). When encountering an `import()`, Webpack will split the code into different chunks and makes sure that they are loaded when needed. \ No newline at end of file diff --git a/website/translated_docs/no-NO/frontend_creating_custom_panels.md b/website/translated_docs/no-NO/frontend_creating_custom_panels.md deleted file mode 100644 index 7b57e82b..00000000 --- a/website/translated_docs/no-NO/frontend_creating_custom_panels.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Creating custom panels" ---- - -Panels are pages that show information within Home Assistant and can allow controlling it. Panels are linked from the sidebar and rendered full screen. They have real-time access to the Home Assistant object via JavaScript. Examples of panels in the app are Map, Logbook and History. - -Besides components registering panels, users can also register panels using the `panel_custom` component. This allows users to quickly build their own custom interfaces for Home Assistant. - -## Introduction - -Panels are defined as custom elements. You can use any framework that you want, as long as you wrap it up as a custom element. To quickly get started with a panel, we've created a [React custom panel starter kit](https://github.com/home-assistant/custom-panel-starter-kit-react). - -## API reference - -The Home Assistant frontend will pass information to your panel by setting properties on your custom element. The following properties are set: - -| Property | Type | Description | -| -------- | ------- | --------------------------------------------------------- | -| hass | object | Current state of Home Assistant | -| narrow | boolean | if the panel should render in narrow mode | -| showMenu | boolean | if the sidebar is currently shown | -| panel | object | Panel information. Config is available as `panel.config`. | - -## JavaScript versions - -The Home Assistant user interface is currently served to browsers in modern JavaScript and older JavaScript (ES5). The older version has a wider browser support but that comes at a cost of size and performance. - -To keep things easy, we advice you to tell your users to force the modern version of the frontend. That way you won't need any build tools while developing your panel. Add this to your config: - -```yaml -# configuration.yaml example -frontend: - javascript_version: latest -``` - -If you do need to run with ES5 support, you will need to load the ES5 custom elements adapter before defining your element: - -```js -window.loadES5Adapter().then(function() { - customElements.define('my-panel', MyCustomPanel) -}); -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/frontend_creating_custom_ui.md b/website/translated_docs/no-NO/frontend_creating_custom_ui.md deleted file mode 100644 index 41cfc105..00000000 --- a/website/translated_docs/no-NO/frontend_creating_custom_ui.md +++ /dev/null @@ -1,118 +0,0 @@ ---- -title: "Creating custom UI" ---- - -### State card - -If you would like to use your own [State card](frontend_add_card.md) without merging your code into [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer/) you can create your own implementation. - -Put the element source file and its dependencies in `www/custom_ui/` directory under your Home Assistant [configuration](https://www.home-assistant.io/docs/configuration/) directory. - -For example if creating a state card for the `light` domain named `state-card-my-custom-light` put `state-card-my-custom-light.html` in `www/custom_ui/`. - -That file should implement `` tag with Polymer. - -In `state-card-my-custom-light.html` you should use `` to import all the dependencies **not** used by Home Assistant's UI. Do not import any dependencies used by the Home Assistant UI. Importing those will work in `development: 1` mode, but will fail in production mode. - -1. In the `customize:` section of the `configuration.yaml` file put `custom_ui_state_card: state-card-my-custom-light`. -2. In the `frontend` section use `extra_html_url` to specify the URL to load. - -Example: - -`configuration.yaml`: - -```yaml -homeassistant: - customize: - light.bedroom: - custom_ui_state_card: state-card-my-custom-light - -frontend: - extra_html_url: - - - /local/custom_ui/state-card-my-custom-light.html -``` - -`www/custom_ui/state-card-my-custom-light.html`: - -```html - - - - - - -``` - -> Some browsers don't support latest ECMAScript standards, these require a separate ES5 compatible file (`extra_html_url_es5`). - -For more possibilities, see the [Custom UI section](https://www.home-assistant.io/cookbook/#user-interface) on our Examples page. - -### More info dialog - -*Introduced in Home Assistant 0.69.* - -Similar to the custom State card, if you would like to use your own [More info dialog](frontend_add_more_info.md) you can create your own implementation. - -Following a similar example, if creating a more info dialog a light named `more-info-my-custom-light` put `more-info-my-custom-light.html` in `www/custom_ui/`. - -1. In the `customize:` section of the `configuration.yaml` file put `custom_ui_more_info: more-info-my-custom-light`. -2. In the `frontend` section use `extra_html_url` to specify the URL to load. - -Example: - -`configuration.yaml`: - -```yaml -homeassistant: - customize: - light.bedroom: - custom_ui_more_info: more-info-my-custom-light - -frontend: - extra_html_url: - - - /local/custom_ui/more-info-my-custom-light.html -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/frontend_data.md b/website/translated_docs/no-NO/frontend_data.md deleted file mode 100644 index 7d3b6c6e..00000000 --- a/website/translated_docs/no-NO/frontend_data.md +++ /dev/null @@ -1,137 +0,0 @@ ---- -title: "Frontend data" -sidebar_label: "Data" ---- - -The frontend passes a single `hass` object around. This object contains the latest state and allows you to send commands back to the server. - -Whenever a state changes, a new version of the objects that changed are created. So you can easily see if something has changed by doing a strict equality check: - -```js -const changed = newVal !== oldVal; -``` - -## Data - -### `hass.states` - -An object containing the states of all entities in Home Assistant. The key is the entity_id, the value is the state object. - -```json -{ - "sun.sun": { - "entity_id": "sun.sun", - "state": "above_horizon", - "attributes": { - "next_dawn": "2018-08-18T05:39:19+00:00", - "next_dusk": "2018-08-17T18:28:52+00:00", - "next_midnight": "2018-08-18T00:03:51+00:00", - "next_noon": "2018-08-18T12:03:58+00:00", - "next_rising": "2018-08-18T06:00:33+00:00", - "next_setting": "2018-08-17T18:07:37+00:00", - "elevation": 60.74, - "azimuth": 297.69, - "friendly_name": "Sun" - }, - "last_changed": "2018-08-17T13:46:59.083836+00:00", - "last_updated": "2018-08-17T13:49:30.378101+00:00", - "context": { - "id": "74c2b3b429c844f18e59669e4b41ec6f", - "user_id": null - }, - }, - "light.ceiling_lights": { - "entity_id": "light.ceiling_lights", - "state": "on", - "attributes": { - "min_mireds": 153, - "max_mireds": 500, - "brightness": 180, - "color_temp": 380, - "hs_color": [ - 56, - 86 - ], - "rgb_color": [ - 255, - 240, - 35 - ], - "xy_color": [ - 0.459, - 0.496 - ], - "white_value": 200, - "friendly_name": "Ceiling Lights", - "supported_features": 151 - }, - "last_changed": "2018-08-17T13:46:59.129248+00:00", - "last_updated": "2018-08-17T13:46:59.129248+00:00", - "context": { - "id": "2c6bbbbb66a84a9dae097b6ed6c93383", - "user_id": null - }, - } -} -``` - -### `hass.user` - -The logged in user. - -```json -{ - "id": "758186e6a1854ee2896efbd593cb542c", - "name": "Paulus", - "is_owner": true, - "credentials": [ - { - "auth_provider_type": "homeassistant", - "auth_provider_id": null - } - ] -} -``` - -## Methods - -All methods starting with `call` are async methods. This means that they will return a `Promise` that will resolve with the result of the call. - -### `hass.callService(domain, service, data)` - -Call a service on the backend. - -```js -hass.callService('light', 'turn_on', { - entity_id: 'light.kitchen' -}); -``` - -### `hass.callWS(message)` - -Call a WebSocket command on the backend. - -```js -this.hass.callWS({ - type: 'config/auth/create', - name: 'Paulus', -}).then(userResponse => - console.log("Created user", userResponse.user.id)); -``` - -### `hass.callApi(method, path, data)` - -Call an API on the Home Assistant server. For example, if you want to fetch all Hass.io snapshots by issuing a GET request to `/api/hassio/snapshots`: - -```js -hass.callApi('get', 'hassio/snapshots') - .then(snapshots => console.log('Received snapshots!', snapshots)); -``` - -If you need to pass in data, pass a third argument: - -```js -hass.callApi('delete', 'notify.html5', { subscription: 'abcdefgh' }); -``` - -*We're moving away from API calls and are migrating everything to `hass.callWS(message)` calls.* \ No newline at end of file diff --git a/website/translated_docs/no-NO/frontend_development.md b/website/translated_docs/no-NO/frontend_development.md deleted file mode 100644 index 5245578a..00000000 --- a/website/translated_docs/no-NO/frontend_development.md +++ /dev/null @@ -1,103 +0,0 @@ ---- -title: "Frontend development" -sidebar_label: "Development" ---- - -The Home Assistant frontend is built using web components and powered by the [Polymer](https://www.polymer-project.org/) framework. - -> Do not use development mode in production. Home Assistant uses aggressive caching to improve the mobile experience. This is disabled during development so that you do not have to restart the server in between changes. - -## Setting up the environment - -> All commands below need to be run from inside the home-assistant-polymer repository. - -### Getting the code - -First step is to fork the [home-assistant-polymer repository](https://github.com/home-assistant/home-assistant-polymer) and add the upstream remote. You can place the forked repository anywhere on your system. - -```bash -$ git clone git@github.com:YOUR_GIT_USERNAME/home-assistant-polymer.git -$ cd home-assistant-polymer -$ git remote add upstream https://github.com/home-assistant/home-assistant-polymer.git -``` - -### Configuring Home Assistant - -You will need to have an instance of Home Assistant set up. See our guide on [setting up a development environment](https://developers.home-assistant.io/docs/en/development_environment.html). - -Next step is to configure Home Assistant to use the development mode for the frontend. Do this by updating the frontend config in your `configuration.yaml` and set the path to the home-assistant-polymer repository that you cloned in the last step: - -```yaml -frontend: - # Example absolute path: /home/paulus/dev/hass/home-assistant-polymer - development_repo: -``` - -### Installing Node.js - -Node.js is required to build the frontend. The preferred method of installing node.js is with [nvm](https://github.com/creationix/nvm). Install nvm using the instructions in the [README](https://github.com/creationix/nvm#install-script), and install the correct node.js by running the following command: - -```bash -$ nvm install -``` - -[Yarn](https://yarnpkg.com/en/) is used as the package manager for node modules. [Install yarn using the instructions here.](https://yarnpkg.com/en/docs/install) - -Next, development dependencies need to be installed to bootstrap the frontend development environment. First activate the right Node version and then download all the dependencies: - -```bash -$ nvm use -$ script/bootstrap -``` - -## Development - -During development, you will need to run the development script to maintain a development build of the frontend that auto updates when you change any of the source files. To run this server, run: - -```bash -$ nvm use -$ script/develop -``` - -Make sure you have cache disabled and correct settings to avoid stale content: - -> Instructions are for Google Chrome - -1. Disable cache by ticking the box in `Network` > `Disable cache` - -

- -

- -2. Enable Bypass for network in `Application` > `Service Workers` > `Bypass for network` - -

- -

- -## Creating pull requests - -If you're planning on issuing a PR back to the Home Assistant codebase you need to fork the polymer project and add your fork as a remote to the Home Assistant Polymer repo. - -```bash -$ git remote add fork -``` - -When you've made your changes and are ready to push them change to the working directory for the polymer project and then push your changes - -```bash -$ git add -A -$ git commit -m "Added new feature X" -$ git push -u fork HEAD -``` - -## Building the Polymer frontend - -If you're making changes to the way the frontend is packaged, it might be necessary to try out a new packaged build of the frontend in the main repository (instead of pointing it at the frontend repo). To do so, first build a production version of the frontend by running `script/build_frontend`. - -To test it out inside Home Assistant, run the following command from the main Home Assistant repository: - -```bash -$ pip3 install -e /path/to/home-assistant-polymer/ -$ hass --skip-pip -``` diff --git a/website/translated_docs/no-NO/frontend_external_auth.md b/website/translated_docs/no-NO/frontend_external_auth.md deleted file mode 100644 index b23f6c1b..00000000 --- a/website/translated_docs/no-NO/frontend_external_auth.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: "External Authentication" ---- - -By default, the frontend will take care of its own authentication tokens. If none found, it will redirect the user to the login page and it will take care that the token is up to date. - -If you want to embed the Home Assistant frontend in an external app, you will want to store the authentication inside the app but make it available to the frontend. To support this, Home Assistant exposes an external authentication API. - -To activate this API, load the frontend with `?external_auth=1` appended to the URL. If this is passed in, Home Assistant will expect either `window.externalApp` (for Android) or `window.webkit.messageHandlers` (for iOS) to be defined containing the methods described below. - -## Get Access Token - -*This API has been introduced in Home Assistant 0.78.* - -When the frontend loads, it will request an access token from the external authentication. It does so by calling one of the following methods with an options object. The options object defines the callback method to be called with the response. - -```js -window.externalApp.getExternalAuth({ - callback: 'externalAuthSetToken' -}); -// or -window.webkit.messageHandlers.getExternalAuth.postMessage({ - callback: 'externalAuthSetToken' -}); -``` - -The response should contain a boolean if it was successful and an object containing an access token and the number of seconds that it will remain valid. Pass the response to the function defined in the options object. - -```js -// To be called by external app -window.externalAuthSetToken(true, { - "access_token": "qwere", - "expires_in": 1800 -}); - -// If unable to get new access token -window.externalAuthSetToken(false); -``` - -The frontend will call this method when the page first loads and whenever it needs a valid token but the previous received token has expired. - -## Revoke Token - -*This API has been introduced in Home Assistant 0.78.* - -When the user presses the logout button on the profile page, the external app will have to [revoke the refresh token](auth_api.md#revoking-a-refresh-token), and log the user out. - -```js -window.externalApp.revokeExternalAuth({ - callback: 'externalAuthSetToken' -}); -// or -window.webkit.messageHandlers.revokeExternalAuth.postMessage({ - callback: 'externalAuthSetToken' -}); -``` - -When done, the external app has to call the function defined in the options object. - -```js -// To be called by external app -window.externalAuthRevokeToken(true); - -// If unable to logout -window.externalAuthRevokeToken(false); -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/frontend_index.md b/website/translated_docs/no-NO/frontend_index.md deleted file mode 100644 index 66fccc8e..00000000 --- a/website/translated_docs/no-NO/frontend_index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: "Home Assistant Frontend" -sidebar_label: "Introduction" ---- - -The Home Assistant frontend allows users to browse and control the state of their house, manage their automations and configure integrations. - -The frontend is designed as a mobile-first experience. It is a progressive web application and offers an app-like experience to our users. - -![Screenshot of the Home Assistant Frontend](/img/en/frontend/frontend-hero.png) \ No newline at end of file diff --git a/website/translated_docs/no-NO/hassio_addon_communication.md b/website/translated_docs/no-NO/hassio_addon_communication.md deleted file mode 100644 index a7615dae..00000000 --- a/website/translated_docs/no-NO/hassio_addon_communication.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: "Add-On Communication" ---- - -There are different ways for communication between add-ons inside Hass.io. - -## Network - -We use an internal network that's allowed to communicate with every add-on, including to/from Home Assistant, by using its name or alias. Only add-ons that run on the host network are limited in that they can talk with all internal add-ons by their name, but all other add-ons can't address these add-ons by name. However, using an alias works for both! - -Names/aliases are used for communication inside Hass.io. The name is generated using the following format: `{REPO}_{SLUG}`, e.g., `local_xy` or `3283fh_myaddon`. In this example, `{SLUG}` is defined in an add-on's `config.json` file. You can use this name as the DNS name also, but you need replace any `_` with `-` to have a valid hostname. If an add-on is installed locally, `{REPO}` will be `local`. If the add-on is installed from a Github repository, `{REPO}` is a hashed identifier generated from the GitHub repository's URL (ex: https://github.com/xy/my_hassio_addons). See [here](https://github.com/home-assistant/hassio/blob/587047f9d648b8491dc8eef17dc6777f81938bfd/hassio/addons/utils.py#L17) to understand how this identifier is generated. Note that this identifier is required in certain service calls that use the [Hass.io add-on API](https://github.com/home-assistant/hassio/blob/dev/API.md#restful-for-api-addons). You can view the repository identifiers for all currently-installed add-ons via a GET request to the hassio API `addons` endpoint. - -Use `hassio` for communication with the internal API. - -## Home Assistant - -An add-on can talk to the [Home Assistant API](https://www.home-assistant.io/developers/rest_api/) using the internal proxy. This makes it very easy to communicate with the API without knowing the password, port or any other information about the Home Assistant instance. Using this URL: `http://hassio/homeassistant/api` ensures that internal communication is redirected to the right place. The next step is to add `homeassistant_api: true` to the `config.json` file and read the environment variable `HASSIO_TOKEN`. Use this as the Home-Assistant password. - -There is also a proxy for the [Home Assistant Websocket API](https://www.home-assistant.io/developers/websocket_api/) that works like the API proxy above and requires `HASSIO_TOKEN` as the password. Use this URL: `http://hassio/homeassistant/websocket`. - -It is also possible to talk directly to the Home Assistant instance, which is named `homeassistant`, over the internal network. However, you'll need to know the configuration that is used by the running instance. - -We have several services for Hass.io inside Home Assistant to run tasks. Send data over STDIN to an add-on to use the `hassio.addon_stdin` service. - -## Hass.io API - -To enable calls to the [Hass.io API](https://github.com/home-assistant/hassio/blob/master/API.md), add `hassio_api: true` to the `config.json` file and read the environment variable `HASSIO_TOKEN`. Now you can use the API over the URL: `http://hassio/`. Use the `HASSIO_TOKEN` with header `X-HASSIO-KEY`. You may also need to change the Hass.io API role to `hassio_role: default`. - -Add-ons can call some API commands without needing to set `hassio_api: true`: - -- `/homeassistant/api` -- `/homeassistant/api/stream` -- `/homeassistant/websocket` -- `/addons/self/*` -- `/services*` -- `/discovery*` -- `/info` - -***Note:*** For Home Assistant API access requirements, see above. \ No newline at end of file diff --git a/website/translated_docs/no-NO/hassio_addon_config.md b/website/translated_docs/no-NO/hassio_addon_config.md deleted file mode 100644 index 2a2caa6f..00000000 --- a/website/translated_docs/no-NO/hassio_addon_config.md +++ /dev/null @@ -1,222 +0,0 @@ ---- -title: "Add-On Configuration" ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - apparmor.txt - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -All our Images have also [bashio](https://github.com/hassio-addons/bashio) installed. It contains a set of commonly used operations and can be used to be included in add-ons to reduce code duplication across add-ons and therefore making it easier to develop and maintain add-ons. - -When developing your script: - -- `/data` is a volume for persistent storage. -- `/data/options.json` contains the user configuration. You can use bashio or `jq` inside your shell script to parse this data. - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain - -```json -{ "target": "beer" } -``` - -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -## Add-on Docker file - -All add-ons are based on latest Alpine Linux. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - - ARG BUILD_FROM - FROM $BUILD_FROM - - ENV LANG C.UTF-8 - - # Install requirements for add-on - RUN apk add --no-cache jq - - # Copy data for add-on - COPY run.sh / - RUN chmod a+x /run.sh - - CMD [ "/run.sh" ] - - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: - - LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" - - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -| ------------- | ------------------------------------------------------------ | -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. | -| BUILD_VERSION | Add-on version (read from `config.json`). | -| BUILD_ARCH | Hold current build arch inside. | - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| ----------------- | ----------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| name | string | yes | Name of the add-on | -| version | string | yes | Version of the add-on | -| slug | string | yes | Slug of the add-on | -| description | string | yes | Description of the add-on | -| arch | list | yes | List of supported arch: `armhf`, `armv7`, `aarch64`, `amd64`, `i386`. | -| machine | list | no | Default it support any machine type. You can select that this add-on run only on specific machines. | -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. | -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. | -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. | -| boot | string | yes | `auto` by system and manual or only `manual` | -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. | -| host_network | bool | no | If that is True, the add-on run on host network. | -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. | -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. | -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. | -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` | -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. | -| homeassistant | string | no | Pin a minimun required Home Assistant version for such Add-on. Value is a version string like `0.91.2`. | -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. | -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. | -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. | -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. | -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH`. | -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. | -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. | -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. | -| environment | dict | no | A dict of environment variable to run add-on. | -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. | -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. | -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. | -| kernel_modules | bool | no | Map host kernel modules and config into add-on (readonly). | -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. | -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. | -| options | dict | yes | Default options value of the add-on | -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. | -| image | string | no | For use with Docker Hub and other container registries. | -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. | -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. | -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` | -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). | -| auth_api | bool | no | Allow access to Home Assistent user backend. | -| ingress | bool | no | Enable the ingress feature for the Add-on | -| ingress_port | integer | no | Default `8099`. For Add-ons they run on host network, you can use `0` and read the port later on API. | -| ingress_entry | string | no | Modify the URL entry point from `/`. | -| panel_icon | string | no | Default: mdi:puzzle. MDI icon for the menu panel integration. | -| panel_title | string | no | Default add-on name, but can Modify with this options. | -| panel_admin | bool | no | Default True. Make menu entry only available with admin privileged. | - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: - -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| ---------- | -------- | ------------------------------------------------------------------------------------------------------ | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. | -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! | -| args | no | Allow to set additional Docker build arguments as a dictionary. | - -We provide a set of [Base-Images](https://github.com/home-assistant/hassio-base) which should cover a lot of needs. If you don't want use the Alpine based version or need a specific Image tag, feel free to pin this requirements for you build with `build_from` option. \ No newline at end of file diff --git a/website/translated_docs/no-NO/hassio_addon_index.md b/website/translated_docs/no-NO/hassio_addon_index.md deleted file mode 100644 index 8b786a49..00000000 --- a/website/translated_docs/no-NO/hassio_addon_index.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Developing an add-on" -sidebar_label: Introduction ---- - -Add-ons for Hass.io allow the user to extend the functionality around Home Assistant. This can be running an application that Home Assistant can integrate with (like an MQTT broker) or to share the configuration via Samba for easy editing from other computers. Add-ons can be configured via the Hass.io panel in Home Assistant. - -Under the hood, add-ons are Docker images published in [Docker Hub](https://hub.docker.com/). Developers can create [GitHub](https://github.com) repositories that contain multiple references to add-ons for easy sharing with the community. - -1. [Tutorial: Making your first add-on](hassio_addon_tutorial.md) -2. [Configuration](hassio_addon_config.md) -3. [Communication](hassio_addon_communication.md) -4. [Local Testing](hassio_addon_testing.md) -5. [Publishing](hassio_addon_publishing.md) -6. [Presentation](hassio_addon_presentation.md) -7. [Repositories](hassio_addon_repository.md) -8. [Security](hassio_addon_security.md) - -Useful links: - -* [Hass.io Supervisor](https://github.com/home-assistant/hassio) -* [Hass.io Core Add-ons](https://github.com/home-assistant/hassio-addons) -* [Hass.io Build environment](https://github.com/home-assistant/hassio-build) -* [Hass.io base images](https://github.com/home-assistant/hassio-base) -* [Hass.io Builder](https://github.com/home-assistant/hassio-builder) -* [Hass.io community Add-ons](https://github.com/hassio-addons) -* [HassOS embedded Linux](https://github.com/home-assistant/hassos) -* [Home Assistant Dockerfile](https://github.com/home-assistant/hassio-homeassistant) \ No newline at end of file diff --git a/website/translated_docs/no-NO/hassio_addon_presentation.md b/website/translated_docs/no-NO/hassio_addon_presentation.md deleted file mode 100644 index 889e8b31..00000000 --- a/website/translated_docs/no-NO/hassio_addon_presentation.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: "Presenting your add-on" ---- - -If you decide to share your add-on to the public, paying attention to details is recommended. Of course, your add-on should have a proper name and description, but Hass.io also gives you some other tools to present your add-on even nicer. - -## Adding documentation - -Good documentation helps the consumer of your add-on to understand its usage, explains configuration options, points users in the right direction in the case they have questions or issues, and contains the license under which the add-on was published. - -This file containing the documentation is usually referred to as the "README", which is generally published as the `README.md` file. - -Take a look at other projects for inspiration. For example, see the `README.md` of the [Community Hass.io Add-ons: Homebridge](https://github.com/hassio-addons/addon-homebridge/blob/master/README.md) add-on. - -In future versions of Hass.io, the `README.md` file will be displayed in the Home Assistant frontend. - -## Add-on icon & logo - -A picture is worth a thousand words. Therefore, your add-on can be improved by adding a proper image icon and logo. Those images are used when showing your add-on in the Home Assistant Hass.io panel and which will significantly improve the visual representation of your add-on. - -Requirements for the logo of your add-on: - -- The logo must be in the Portable Network Graphics format (`.png`). -- The filename must be `logo.png`. -- It is recommended to keep the logo size around 250x100px. You may choose to use a different size or aspect ratio as you seem fit for your add-on. - -Requirements for the icon of your add-on: - -- The icon must be in the Portable Network Graphics format (`.png`). -- The filename must be `icon.png`. -- The aspect ratio of the icon must be 1x1 (square). -- It is recommended to use an icon size of 128x128px. - -## Keeping a changelog - -It is likely you are going to release newer versions of your add-on in the future. In case that happens, the users of your add-on would see an upgrade notice and probably want to know what changes were made in the latest version. - -A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of your add-on and is generally published as the `CHANGELOG.md` file. - -If you are in need of a guide on keeping a changelog, we would recommend checking the [keep a changelog](http://keepachangelog.com) website. They have developed a standard that is used by many opensource projects around the world. - -In future versions of Hass.io, the `CHANGELOG.md` file will be displayed in the Home Assistant frontend. - -## AppArmor - -You can use own security profile for you Add-on with AppArmor. Default it is enabled and use the Docker default profile. Put `apparmor.txt` file into your Add-on folder and it will load this file as primary profile. Use the config options to set the name of that profile. - -## Ingress - -Ingress allow users to access the add-on web interface via the Home Assistant UI. Authentication is handled by Home Assistant, so neither the user nor the add-on developer will need to care about the security or port forwarding. Users love this feature, however it is not every time simple to implement for the add-on developer. - -To add Ingress support, follow the following steps: - -- The add-on will need to provide the web interface on port `8099`. Make sure that the add-on accepts only connections from `172.30.32.2` on that port and that the connections are treated as authenticated. -- Update add-on configuration and set `ingress: true`. Here it is also possible to configure the Ingress port (default 8099). -- If you need to configure the application inside your add-on with the right path and port, query the add-on info API endpoint. -- If the application doesn't support relative paths or you can't set a base url, you can use nginx filter to replace the URL with correct path. - -Ingress API gateway supports the following: - -- HTTP/1.x -- Streaming content -- Websockets \ No newline at end of file diff --git a/website/translated_docs/no-NO/hassio_addon_publishing.md b/website/translated_docs/no-NO/hassio_addon_publishing.md deleted file mode 100644 index 38b48bac..00000000 --- a/website/translated_docs/no-NO/hassio_addon_publishing.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: "Publishing your add-on" ---- - -There are two different ways of publishing add-ons. One is to publish pre-build containers to Docker Hub and the other option is to have users build the containers locally on their Hass.io instance. - -#### Pre-build containers - -With pre-build containers, the developer is responsible for building the images for each architecture on their machine and push the results out to Docker Hub. This has a lot of advantages for the user. As a user it will only have to download the final container and be up and running once the download finishes. This makes the installation process fast and almost no chance of failure. This is the preferred method. - -We have automated the process of building and publishing add-ons. See below for the instructions. - -#### Locally build containers - -Starting Hass.io 0.26, it is possible to distribute add-ons that will be built on the users machine. The advantage is that as a developer it is easy to test an idea and see if people are interested in your add-ons. This method includes installing and potentially compiling code. This means that installing such an add-on is slow and adds more wear and tear to users SD card/hard drive than the above mentioned pre-build solution. It also has a higher chance of failure if one of the dependencies of the container has changed or is no longer available. - -Use this option when you are playing with add-ons and seeing if someone is interested in your work. Once you're an established repository, please migrate to pushing builds to Docker Hub as it greatly improves the user experience. In the future we will mark locally built add-ons in the add-on store to warn users. - -## Build scripts to publish add-ons to Docker Hub - -All add-ons are simple docker containers. Inside your add-on `config.json` you specify the Docker image that will be installed for your add-on: - -```json -{ - ... - "image": "myhub/image-{arch}-addon-name", - ... -} -``` - -You can use `{arch}` inside the image name to support multiple architectures with one (1) configuration file. It will be replaced with the architecture of the user when we load the image. If you use `Buildargs` you can use the `build.json` to overwrite our default args. - -Hass.io assumes that the `master` branch of your add-on repository matches the latest tag on Docker Hub. When you're building a new version, it's suggested that you use another branch, ie `build` or do it with a PR on GitHub. After you push the add-on to [Docker Hub](https://hub.docker.com/), you can merge this branch to master. - -## Custom Add-ons - -You need a Docker Hub account to make your own add-ons. You can build your Docker images with the Docker `build` command or use our script that make it simple. Pull our [Builder Docker engine](https://github.com/home-assistant/hassio-builder) and run one of the following commands. - -For a git repository: - -```bash -$ docker run --rm --privileged -v \ - ~/.docker:/root/.docker homeassistant/amd64-builder \ - --all -t addon-folder -r https://github.com/xy/addons \ - -b branchname -``` - -For a local repository: - -```bash -$ docker run --rm --privileged -v \ - ~/.docker:/root/.docker -v /my_addon:/data homeassistant/amd64-builder \ - --all -t /data -``` - -> If you are developing on macOS and using Docker for Mac, you may encounter an error message similar to the following: `error creating aufs mount to /var/lib/docker/aufs/mnt/-init: invalid argument`. A proposed workaround is to add the following to the Advanced Daemon JSON configuration via Docker > Preferences > Daemon > Advanced: `"storage-driver" : "aufs"` or map the docker socket into container. \ No newline at end of file diff --git a/website/translated_docs/no-NO/hassio_addon_repository.md b/website/translated_docs/no-NO/hassio_addon_repository.md deleted file mode 100644 index 8ad68672..00000000 --- a/website/translated_docs/no-NO/hassio_addon_repository.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: "Create an add-on repository" ---- - -An add-on repository can contain one or more add-ons. Each add-on is stored in its own unique folder. To be indentified as a repository, the repository must contain a configuration file. - -Check the [Example add-on repository](https://github.com/home-assistant/hassio-addons-example) for further details. - -## Installing a repository - -A user can add a repository by going to the Hass.io panel in Home Assistant, clicking on the store icon in the top right, copy/paste the URL of your repostory into the repository textarea and click on **Save**. - -## Repository configuration - -Each repository is required to contain `repository.json` at the root in the git repository. - -```json -{ - "name": "Name of repository", - "url": "http://www.example/addons", - "maintainer": "HomeAssistant Team " -} -``` - -| Key | Required | Description | -| ---------- | -------- | --------------------------------------------------------------------- | -| name | yes | Name of the repository | -| url | no | Homepage of the repository. Here you can explain the various add-ons. | -| maintainer | no | Contact info of the maintainer. | \ No newline at end of file diff --git a/website/translated_docs/no-NO/hassio_addon_security.md b/website/translated_docs/no-NO/hassio_addon_security.md deleted file mode 100644 index d012a5fb..00000000 --- a/website/translated_docs/no-NO/hassio_addon_security.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "Add-on security" ---- - -Hass.io rates every add-on based on the wanted rights. An add-on with a rating of 6 is very secure. If an add-on has a rating of 1, you shouldn't run this add-on unless you are 100% sure that you can trust the source. - -## API Role - -For access to Hass.io API you need define a role or you run in default mode. This is only required for Hass.io API not Home Assistant proxy. Any of the roles already have access to the default API calls, and do not require any additional settings. - -### Available Roles - -| Role | Description | -| ------------- | ------------------------------------------------------------------------------------------------------ | -| default | Have access to all `info` calls | -| homeassistant | Can access all Home Assistant API endpoints | -| backup | Can access all snapshot API endpoints | -| manager | Is for Add-ons that run CLIs and need extended rights | -| admin | Have access to every API call. That is the only one they can disable/enable the Add-on protection mode | - -## Protection - -Default, all add-ons run in protection enabled mode. This mode prevents the add-on from getting any rights on the system. If an add-on requires more rights, you can disable this protection via the API add-on options for that add-on. But be careful, an add-on with disabled protection can destroy your system! - -## Making a secure add-on - -As a developer, follow the following best practices to make your add-on secure: - -- Don't run on host network -- Create an AppArmor profile -- Map folders read only if you don't need write access -- If you need any API access, make sure that you do not grant permission that aren't needed - -## Use Home Assistant User backend - -Instead of allowing users to set new login credential in plain text config, use the Home Assistant [Auth backend](https://github.com/home-assistant/hassio/blob/dev/API.md#auth--sso-api). You can enable the access to API with `auth_api: true`. Now you are able to send the login credential to auth backend and validate it again Home Assistant. - -We have some sample and helpers around that system collected in a [GitHub repository](https://github.com/home-assistant/hassio-auth). Feel free to copy and paste it or provide your own scripts. \ No newline at end of file diff --git a/website/translated_docs/no-NO/hassio_addon_testing.md b/website/translated_docs/no-NO/hassio_addon_testing.md deleted file mode 100644 index 2d089763..00000000 --- a/website/translated_docs/no-NO/hassio_addon_testing.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Local add-on testing" ---- - -The fastest way to develop add-ons is by adding them to your local add-on repository. To access your local add-on repository, install either the [Samba add-on](https://www.home-assistant.io/addons/samba/) or [SSH add-on](https://www.home-assistant.io/addons/ssh/). - -Right now add-ons will work with images that are stored on Docker Hub (using `image` from add-on config). Without `image` inside local add-ons repository it to be built on the device. - -The [Community Add-on](https://github.com/hassio-addons/hassio-vagrant) repository create a vagrant based development system. This Vagrant virtual machine allows you to test and play with Hass.io and Home Assistant, and is a great environment for add-on developers - -## Local build - -You can build and try the addon on your developer machine also. Move all addon stuff into a temp folder. If you use `FROM $BUILD_FROM` you need set a base image with build args. Normally you can use follow base images: - -- armhf: `homeassistant/armhf-base:latest` -- aarch64: `homeassistant/aarch64-base:latest` -- amd64: `homeassistant/amd64-base:latest` -- i386: `homeassistant/i386-base:latest` - -Use `docker` to build the test addon: `docker build --build-arg BUILD_FROM="homeassistant/amd64-base:latest" -t local/my-test-addon .` - -## Local run - -Create a new folder for data and add a test *options.json* file. After that you can run your add-on with: `docker run --rm -v /tmp/my_test_data:/data -p PORT_STUFF_IF_NEEDED local/my-test-addon` - -## Logs - -All stdout and stderr are redirected to the Docker logs. The logs can be fetched from the add-on page inside the Hass.io panel in Home Assistant. \ No newline at end of file diff --git a/website/translated_docs/no-NO/hassio_addon_tutorial.md b/website/translated_docs/no-NO/hassio_addon_tutorial.md deleted file mode 100644 index 7d90afee..00000000 --- a/website/translated_docs/no-NO/hassio_addon_tutorial.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: "Tutorial: Making your first add-on" ---- - -So you've got Home Assistant going and you've been enjoying the built-in add-ons but you're missing this one application. Time to make your own add-on! In Hass.io 0.24 we introduced the option to have local add-ons be build on your device. This is great for developing new add-ons locally. - -To get started with developing add-ons, we first need access to where Hass.io looks for local add-ons. For this you can use the Samba add-on or the SSH add-on. - -For Samba, once you have enabled and started it, your Hass.io instance will show up in your local network tab and share a folder called "addons". This is the folder to store your custom add-ons. - -If you are on macOS and the folder is not showing up automatically, go to Finder and press CMD+K then enter 'smb://hassio.local' - -![Screenshot of Windows Explorer showing a folder on the Hass.io server](/img/en/hass.io/tutorial/samba.png) - -For SSH, you will have to install it. Before you can start it, you will have to have a private/public key pair and store your public key in the add-on config ([see docs for more info](https://www.home-assistant.io/addons/ssh/)). Once started, you can SSH to Hass.io and store your custom add-ons in "/addons". - -![Screenshot of Putty connected to Hass.io](/img/en/hass.io/tutorial/ssh.png) - -Once you have located your add-on directory, it's time to get started! - -## Step 1: The basics - -- Create a new directory called `hello_world` -- Inside that directory create three files. - -`Dockerfile`: - - ARG BUILD_FROM - FROM $BUILD_FROM - - ENV LANG C.UTF-8 - - # Copy data for add-on - COPY run.sh / - RUN chmod a+x /run.sh - - CMD [ "/run.sh" ] - - -`config.json`: - -```json -{ - "name": "Hello world", - "version": "1", - "slug": "hello_world", - "description": "My first real add-on!", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {} -} -``` - -`run.sh`: - -```bash -echo Hello world! -``` - -Make sure your editor is using UNIX-like line breaks (LF), not Dos/Windows (CRLF). - -## Step 2: Installing and testing your add-on - -Now comes the fun part, time to open the Hass.io UI and install and run your add-on. - -- Open the Home Assistant frontend -- Go to the Hass.io panel -- On the top right click the shopping basket to go to the add-on store. - -![Screenshot of the Hass.io main panel](/img/en/hass.io/screenshots/main_panel_addon_store.png) - -- On the top right click the refresh button -- You should now see a new card called "Local" that lists your add-on! - -![Screenshot of the local repository card](/img/en/hass.io/screenshots/local_repository.png) - -- Click on your add-on to go to the add-on details page. -- Install your add-on -- Start your add-on -- Refresh the logs of your add-on, you should now see "Hello world!" in your logs. - -![Screenshot of the add-on logs](/img/en/hass.io/tutorial/addon_hello_world_logs.png) - -### I don't see my add-on?! - -Oops! You clicked refresh in the store and your add-on didn't show up. Or maybe you just updated an option, clicked refresh and saw your add-on disappear. - -When this happens, it means that your `config.json` is invalid. It's either invalid JSON or one of the specified options is incorrect. To see what went wrong, go to the Hass.io panel and in the supervisor card click on "View logs". This should bring you to a page with the logs of the supervisor. Scroll to the bottom and you should be able to find the validation error. - -Once you fixed the error, go to the add-on store and click refresh again. - -## Step 3: Hosting a server - -Until now we've been able to do some basic stuff, but it's not very useful yet. So let's take it one step further and host a server that we expose on a port. For this we're going to use the built-in HTTP server that comes with Python 3. - -To do this, we will need to update our files as follows: - -- `Dockerfile`: Install Python 3 -- `config.json`: Make the port from the container available on the host -- `run.sh`: Run the Python 3 command to start the HTTP server - -Add to your `Dockerfile` before `RUN`: - - # Install requirements for add-on - RUN apk add --no-cache python3 - - # Python 3 HTTP Server serves the current working dir - # So let's set it to our add-on persistent data directory. - WORKDIR /data - - -Add "ports" to `config.json`. This will make TCP on port 8000 inside the container available on the host on port 8000. - -```json -{ - "name": "Hello world", - "version": "0.2", - "slug": "hello_world", - "description": "My first real add-on!", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {}, - "ports": { - "8000/tcp": 8000 - } -} -``` - -Update `run.sh` to start the Python 3 server: - - python3 -m http.server - - -## Step 4: Installing the update - -Since we updated the version number in our `config.json`, Home Assistant will show an update button when looking at the add-on details. You might have to refresh your browser or click the refresh button in the add-on store for it to show up. If you did not update the version number, you can also uninstall and install the add-on again. After installing the add-on again, make sure you start it. - -Now navigate to to see our server in action! - -![Screenshot of the file index served by the add-on](/img/en/hass.io/tutorial/python3-http-server.png) - -## Bonus: Working with add-on options - -In the screenshot you've probably seen that our server only served up 1 file: `options.json`. This file contains the user configuration for this add-on. Because we specified an empty "config" and "schema" in our `config.json`, the file is currently empty. - -Let's see if we can get some data into that file! - -To do this, we need to specify the default options and a schema for the user to change the options. - -Change the options and schema entries in your `config.json` with the following: - -```json -{ - … - - "options": { - "beer": true, - "wine": true, - "liquor": false, - "name": "world", - "year": 2017 - }, - "schema": { - "beer": "bool", - "wine": "bool", - "liquor": "bool", - "name": "str", - "year": "int" - }, - - … -} -``` - -Refresh the add-on store and re-install your add-on. You will now see the options available in the add-on config screen. When you now go back to our Python 3 server and download `options.json`, you'll see the options you set. [Example of how options.json can be used inside `run.sh`](https://github.com/home-assistant/hassio-addons/blob/master/mosquitto/run.sh#L4-L6) \ No newline at end of file diff --git a/website/translated_docs/no-NO/hassio_debugging.md b/website/translated_docs/no-NO/hassio_debugging.md deleted file mode 100644 index 0ec57a76..00000000 --- a/website/translated_docs/no-NO/hassio_debugging.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: "Debugging Hass.io" ---- - -> This section is not for end users. End users should use the [SSH add-on](https://www.home-assistant.io/addons/ssh/) to SSH into Hass.io. This is for **developers** of Hass.io. Do not ask for support if you are using these options. - -The following debug tips and tricks are for developers who are running the Hass.io image and are working on the base image. If you use the generic Linux installer script, you should be able to access your host and logs as per your host. - -## Debug Supervisor - -Visual Studio Code config: - -```json -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Hass.io remote debug", - "type": "python", - "request": "attach", - "port": 33333, - "host": "IP", - "pathMappings": [ - { - "localRoot": "${workspaceFolder}", - "remoteRoot": "/usr/src/hassio" - } - ] - } - ] -} -``` - -You need set the dev mode on supervisor and enable debug with options. You need also install the Remote debug Add-on from Developer Repository to expose the debug port to Host. - -## SSH access to the host - -### resinOS based Hass.io (deprecated) - -Create an `authorized_keys` file containing your public key, and place it in the root of the boot partition of your SD card. See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. Once the device is booted, you can access your device as root over SSH on port 22222. - -### HassOS based Hass.io - -Use a USB drive formatted with FAT, ext4, or NTFS and name it CONFIG (case sensitive). Create an `authorized_keys` file (no extension) containing your public key, and place it in the root of the USB drive. See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. From the UI, navigate to the hass.io system page and choose "Import from USB". You can now access your device as root over SSH on port 22222. Alternatively, the file will be imported from the USB when the hass.io device is rebooted. - -> Make sure when you are copying the public key to the root of the USB drive that you rename the file correctly to `authorized_keys` with no `.pub` file extension. - -You should then be able to SSH into your Hass.io device. On Mac/Linux, use: - - ssh root@hassio.local -p 22222 - - -You will initially be logged in to Hass.io CLI for HassOS where you can perform normal [CLI functions](https://www.home-assistant.io/hassio/commandline/). If you need access to the host system use the 'login' command. [Hass.io OS](https://github.com/home-assistant/hassos) is a hypervisor for Docker. See the [Hass.io Architecture](https://developers.home-assistant.io/docs/en/architecture_hassio.html) documentation for information regarding the Hass.io supervisor. The supervisor offers an API to manage the host and running the Docker containers. Home Assistant itself and all installed addon's run in separate Docker containers. - -## Checking the logs - -```bash -# Logs from the supervisor service on the Host OS -journalctl -f -u hassos-supervisor.service - -# Hass.io supervisor logs -docker logs hassos_supervisor - -# Home Assistant logs -docker logs homeassistant -``` - -## Accessing the container bash - -```bash -docker exec -it homeassistant /bin/bash -``` - -### Generating SSH Keys - -Windows instructions for how to generate and use private/public keys with Putty are [here](https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-putty-on-digitalocean-droplets-windows-users). Instead of the droplet instructions, add the public key as per above instructions. - -Alternative instructions, for Mac, Windows and Linux can be found [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#platform-mac). - -Follow steps 1-4 under 'Generating a new SSH key' (The other sections are not applicable to Hass.io and can be ignored.) - -Step 3 in the link above, shows the path to the private key file `id_rsa` for your chosen operating system. Your public key, `id_rsa.pub`, is saved in the same folder. Next, select all text from text box "Public key for pasting into the authorized_keys file" and save it to the root of your USB drive as `authorized_keys`. \ No newline at end of file diff --git a/website/translated_docs/no-NO/hassio_hass.md b/website/translated_docs/no-NO/hassio_hass.md deleted file mode 100644 index 90542d61..00000000 --- a/website/translated_docs/no-NO/hassio_hass.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "Hass.io <> Home Assistant integration development" -sidebar_label: "Integration development" ---- - -These steps will help you connect your local Home Assistant to a remote Hass.io instance. You can then make changes locally to either the Hass.io component or the frontend and test it out against a real instance. - -For this guide, we're going to assume that you have an Hass.io instance up and running. If you don't, you can use the generic installation method to install it inside a [virtual machine](https://github.com/home-assistant/hassio-build/tree/master/install#install-hassio). - -## API Access - -To develop for the frontend, we're going to need API access to the supervisor. - -- Add our developer Add-on repository: https://github.com/home-assistant/hassio-addons-development -- Install the Add-on "Remote API proxy" - -For some API commands you need explicit the Home Assistant API token, but 99% of the functionality work with `Remote API proxy`. This token change some times but you can read the current legal token on host system with: - -```sh -$ docker inspect homeassistant | grep HASSIO_TOKEN -``` - -## Having Home Assistant connect to remote Hass.io - -The connection with the supervisor is hidden inside the host and is only accessible from applications running on the host. So to make it accessible for our Home Assistant instance, we will need to route the connection to our computer running Home Assistant. We're going to do this by forwarding the API with "Remote API proxy" Add-on. - -First, make sure Home Assistant will load the Hass.io component by adding `hassio:` to your `configuration.yaml` file. Next, we will need to tell Hass.io component how to connect to the remote Hass.io instance, we do this by setting the `HASSIO` and `HASSIO_TOKEN` environment variables when starting Home Assistant. Note that the `HASSIO` value is not the same as the one that we saw above and the `HASSIO_TOKEN` is available inside log output of "Remote API Add-on" (This change every restart of this Add-on!). - -```bash -HASSIO=:80 HASSIO_TOKEN= hass -``` - -Voila. Your local Home Assistant installation will now connect to a remote Hass.io instance. - -## Frontend development - -> This requires Home Assistant 0.71 or later. - -We need a couple more steps to do frontend development. First, make sure you have a Home Assistant frontend development set up ([instructions](frontend_index.md)). - -Update the Hass.io component configuration in your `configuration.yaml` to point at the frontend repository: - -```yaml -# configuration.yaml -hassio: - development_repo: /home/paulus/dev/hass/home-assistant-polymer -``` - -To build a local version of the Hass.io panel, go to the frontend repository and run: - -```bash -cd hassio -script/build_hassio -``` - -Now start Home Assistant as discussed in the previous section and it will now connect to the remote Hass.io but show your local frontend. - -We're currently transitioning in how we're building the frontend so we don't have an incremental development mode just yet. For now, after making a local change, run `script/build_hassio` again. \ No newline at end of file diff --git a/website/translated_docs/no-NO/integration_quality_scale_index.md b/website/translated_docs/no-NO/integration_quality_scale_index.md deleted file mode 100644 index 03c552a1..00000000 --- a/website/translated_docs/no-NO/integration_quality_scale_index.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Integration Quality Scale" -sidebar_label: "Integration Quality Scale" ---- - -The Integration Quality Scale scores each integration based on the code quality and user experience. Each level of the quality scale consists of a list of requirements. If an integration matches all requirements, it's considered to have reached that level. - -> Suggestions for changes can be done by creating an issue in the [architecture repo](https://github.com/home-assistant/architecture/issues/). - -# No score - -This integration passes the bare minimum requirements to become part of the index. - -- Satisfy all requirements for [creating components](creating_component_code_review.md) and [creating platforms](creating_platform_code_review.md). -- Configurable via `configuration.yaml` - -# Silver 🥈 - -This integration is able to cope when things go wrong. It will not print any exceptions nor will it fill the log with retry attempts. - -- Connection/configuration is handled via a component. -- Set an appropriate `SCAN_INTERVAL` (if a polling integration) -- Raise `PlatformNotReady` if unable to connect during platform setup (if appropriate) -- Handles expiration of auth credentials. Refresh if possible or print correct error and fail setup. If based on a config entry, should trigger a new config entry flow to re-authorize. -- Handles internet unavailable. Log a warning once when unavailable, log once when reconnected. -- Handles device/service unavailable. Log a warning once when unavailable, log once when reconnected. -- Set `available` property to `False` if appropriate ([docs](entity_index.md#generic-properties)) -- Entities have unique ID (if available) ([docs](entity_registry_index.md#unique-id-requirements)) - -# Gold 🥇 - -This is a solid integration that is able to survive poor conditions and can be configured via the user interface. - -- Configurable via config entries. - - Don't allow configuring already configured device/service (example: no 2 entries for same hub) - - Tests for the config flow - - Discoverable (if available) -- Entities have device info (if available) ([docs](device_registry_index.md#defining-devices)) -- States are translated in the frontend (text-based sensors only, [docs](internationalization_index.md)) -- Tests for reading data from/controlling the integration ([docs](development_testing.md)) -- Has a code owner - -# Platinum 🏆 - -Best of the best. The integration is completely async, meaning it's super fast. Integrations that reach platinum level will require approval by the code owner for each PR. - -- Set appropriate `PARALLEL_UPDATES` constant -- Support config entry unloading (called when config entry is removed) -- Integration + dependency are async -- Uses aiohttp and allows passing in websession (if making HTTP requests) - -# Internal 🏠 - -Integrations which are part of Home Assistant are not rated but marked as **internal**. \ No newline at end of file diff --git a/website/translated_docs/no-NO/intent_builtin.md b/website/translated_docs/no-NO/intent_builtin.md deleted file mode 100644 index 9ea35895..00000000 --- a/website/translated_docs/no-NO/intent_builtin.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "Built-in intents" ---- - -Home Assistant comes with a couple of built-in intents. These intents aim to offer similar functionality as exposed via the services. All built-in intents are prefixed with "Hass" to avoid collision with user defined intents. - -## Core - -### HassTurnOff - -Turn an entity off. - -| Slot name | Type | Required | Description | -| --------- | ------ | -------- | ------------------------------- | -| name | string | Yes | Name of the entity to turn off. | - -### HassTurnOn - -Turn an entity on. - -| Slot name | Type | Required | Description | -| --------- | ------ | -------- | ------------------------------ | -| name | string | Yes | Name of the entity to turn on. | - -### HassToggle - -Toggle the state of an entity. - -| Slot name | Type | Required | Description | -| --------- | ------ | -------- | ----------------------------- | -| name | string | Yes | Name of the entity to toggle. | - -## Cover - -### HassOpenCover - -Open a cover. - -| Slot name | Type | Required | Description | -| --------- | ------ | -------- | --------------------------------- | -| name | string | Yes | Name of the cover entity to open. | - -### HassCloseCover - -Close a cover. - -| Slot name | Type | Required | Description | -| --------- | ------ | -------- | ---------------------------------- | -| name | string | Yes | Name of the cover entity to close. | - -## Light - -### HassLightSet - -Set the state of a light. - -| Slot name | Type | Required | Description | -| ---------- | --------------------------- | -------- | ---------------------------------- | -| name | string | Yes | Name of the entity to toggle. | -| color | string, name of valid color | No | Color to change the light to. | -| brightness | integer, 0-100 | No | Brightness to change the light to. | - -## Shopping List - -### HassShoppingListAddItem - -Add an item to the shopping list. - -| Slot name | Type | Required | Description | -| --------- | ------ | -------- | -------------------------------- | -| item | string | Yes | Name of item to add to the list. | - -### HassShoppingListLastItems - -List the last 5 items on the shopping list. - -*This intent has no slots.* \ No newline at end of file diff --git a/website/translated_docs/no-NO/intent_conversation.md b/website/translated_docs/no-NO/intent_conversation.md deleted file mode 100644 index e80639ec..00000000 --- a/website/translated_docs/no-NO/intent_conversation.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: "Registering sentences" ---- - -The conversation component handles incoming commands from the frontend and converts them to intents. It does this based on registered sentences. - -As a component, you can register sentences with the conversation component to allow it to be remote controlled. Refer to named slots by putting the slot name between curly braces: `{item}`. Use square brackets around (partial) words to mark them as optional. - -Example code: - -```python -async def async_setup(hass, config): - hass.components.conversation.async_register('MyCoolIntent', [ - 'I think that {object} is [very] cool', - 'Nothing is cooler than {object}' - ]) -``` - -If a sentence like "I think that beer is cool" comes in, the conversation component will generate an intent of type `MyCoolIntent` and with 1 slot, named `object` and value `beer`. \ No newline at end of file diff --git a/website/translated_docs/no-NO/intent_firing.md b/website/translated_docs/no-NO/intent_firing.md deleted file mode 100644 index e46e3c7e..00000000 --- a/website/translated_docs/no-NO/intent_firing.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "Firing intents" ---- - -When you fire an intent, you will get a response back or an error will be raised. It is up to the component to return the result to the user. - -Example code to handle an intent in Home Assistant. - -```python -from homeassistant.helpers import intent - -intent_type = 'TurnLightOn' -slots = { - 'entity': { 'value': 'Kitchen' } -} - -try: - intent_response = yield from intent.async_handle( - hass, 'example_component', intent_type, slots - ) - -except intent.UnknownIntent as err: - _LOGGER.warning('Received unknown intent %s', intent_type) - -except intent.InvalidSlotInfo as err: - _LOGGER.error('Received invalid slot data: %s', err) - -except intent.IntentError: - _LOGGER.exception('Error handling request for %s', intent_type) -``` - -The intent response is an instance of `homeassistant.helpers.intent.IntentResponse`. - -| Name | Type | Description | -| -------- | ---------- | --------------------------------------------------------------------------- | -| `intent` | Intent | Instance of intent that triggered response. | -| `speech` | Dictionary | Speech responses. Each key is a type. Allowed types are `plain` and `ssml`. | -| `card` | Dictionary | Card responses. Each key is a type. | - -Speech dictionary values: - -| Name | Type | Description | -| ------------ | ------ | ----------------------------------------- | -| `speech` | String | The text to say | -| `extra_data` | Any | Extra information related to this speech. | - -Card dictionary values: - -| Name | Type | Description | -| --------- | ------ | ----------------------- | -| `title` | String | The title of the card | -| `content` | Any | The content of the card | \ No newline at end of file diff --git a/website/translated_docs/no-NO/intent_handling.md b/website/translated_docs/no-NO/intent_handling.md deleted file mode 100644 index dc06e4e0..00000000 --- a/website/translated_docs/no-NO/intent_handling.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Handling intents" ---- - -Any component can register to handle intents. This allows a single component to handle intents fired from multiple voice assistants. - -A component has to register an intent handler for each type that it wants to handle. Intent handlers have to extend `homeassistant.helpers.intent.IntentHandler` - -```python -import asyncio -from homeassistant.helpers import intent - -DATA_KEY = 'example_key' - -@asyncio.coroutine -def async_setup(hass, config): - hass.data[DATA_KEY] = 0 - intent.async_register(hass, CountInvocationIntent()) - - -class CountInvocationIntent(intent.IntentHandler): - """Handle CountInvocationIntent intents.""" - - # Type of intent to handle - intent_type = 'CountInvocationIntent' - - # Optional. A validation schema for slots - # slot_schema = { - # 'item': cv.string - # } - - @asyncio.coroutine - def async_handle(self, intent_obj): - """Handle the intent.""" - intent_obj.hass.data[DATA_KEY] += 1 - - response = intent_obj.create_response() - response.async_set_speech( - "This intent has been invoked {} times".format( - intent_obj.hass.data[DATA_KEY])) - return response -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/intent_index.md b/website/translated_docs/no-NO/intent_index.md deleted file mode 100644 index 0e055c9f..00000000 --- a/website/translated_docs/no-NO/intent_index.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: "Intents" -sidebar_label: "Introduction" ---- - -An intent is a description of a user's intention. Intents are generated by user actions, like asking Amazon Echo to turn on a light. - - - Architectural overview of intents in Home Assistant - - -Intents are fired by components that receive them from external sources/services. Conversation, Alexa, API.ai and Snips are currently sourcing intents. - -Any component can handle intents. This makes it very easy for developers to integrate with all voice assistants at once. - -Intents are implemented using the `homeassistant.helpers.intent.Intent` class. It contains the following properties: - -| Name | Type | Description | -| ------------- | -------------- | ------------------------------------------------------- | -| `hass` | Home Assistant | The Home Assistant instance that fired the intent. | -| `platform` | string | The platform that fired the intent | -| `intent_type` | string | The type (name) of the intent | -| `slots` | dictionary | Contains the slot values keyed by slot name. | -| `text_input` | string | Optional. The raw text input that initiated the intent. | - -Description of the slots dictionary values. - -| Name | Type | Description | -| ----- | -------- | ------------------ | -| Value | anything | Value of the slot. | \ No newline at end of file diff --git a/website/translated_docs/no-NO/internationalization_backend_localization.md b/website/translated_docs/no-NO/internationalization_backend_localization.md deleted file mode 100644 index 53ffb2c8..00000000 --- a/website/translated_docs/no-NO/internationalization_backend_localization.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: "Backend Localization" ---- - -## Translation Strings - -Platform translation strings are stored as JSON in the [home-assistant](https://github.com/home-assistant/home-assistant) repository. These files must be located adjacent to the component/platform they belong to. Components must have their own directory, and the file is simply named `strings.json` in that directory. For platforms, they are named `strings..json` in the platform directory. This file will contain the different strings that will be translatable. - -In order to test changes to translation files, the translation strings must be compiled into Home Assistant’s translation directories by running the following script: - -```bash -$ script/translations_develop -``` - -After the pull request with the strings file is merged into the `dev` branch, the strings will be automatically uploaded to Lokalise, where contributors can submit translations. The translated strings in Lokalise will be periodically pulled in to the home-assistant repository. - -## States Localization - -The first step when localizing platform states is to ensure that the states defined in the actual platform code are defined in `snake_case`. The states should not contain capital letters or spaces. Next, the strings file needs to be created. The states should exist under the `state` key, and map the backend state keys to their English translations. [The season sensor localization](https://github.com/home-assistant/home-assistant/pull/12453/commits/bb2f328ce10c3867990e34a88da64e2f8dc7a5c4) is a good example. - -## Configuration Flow Localization - -The translation strings for the configuration flow handler are defined under the `config` key. An example strings file below describes the different supported keys: - -```json -{ - "config": { - "title": "This title is shown in the integrations list", - "step": { - "init": { - "title": "The user visible title of the `init` step.", - "description": "Markdown that is shown with the step.", - "data": { - "api_key": "The label for the `api_key` input field" - } - } - }, - "error": { - "invalid_api_key": "This message will be displayed if `invalid_api_key` is returned as a flow error." - }, - "abort": { - "stale_api_key": "This message will be displayed if `stale_api_key` is returned as the abort reason." - } - } -} -``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/internationalization_custom_component_localization.md b/website/translated_docs/no-NO/internationalization_custom_component_localization.md deleted file mode 100644 index da2dc8c1..00000000 --- a/website/translated_docs/no-NO/internationalization_custom_component_localization.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: "Custom Component Localization" ---- - -## Translation Strings - -Unlike localized strings merged in the `home-assistant` repository, custom components cannot take advantage of Lokalise for user submitted translations. However, custom component authors can still include translations with their components. These will be read from the `.translations` directory, adjacent to the component source. They are named `..json`, e.g., for the German translation of a sensor `sensor.de.json`, unless the translation is for the custom component only, in which case the file is simply named `.json` in the `.translations` directory. - -These files follow the same formatting as [backend translation string files](internationalization_backend_localization.md), but a copy will exist for each translated language. - -The language codes follow the [BCP47](https://tools.ietf.org/html/bcp47) format. The [frontend translation files](https://github.com/home-assistant/home-assistant-polymer/tree/master/translations) can also be referred to if you are unsure of the correct language code to use. - -The frontend will serve these files after Home Assistant is restarted. \ No newline at end of file diff --git a/website/translated_docs/no-NO/internationalization_index.md b/website/translated_docs/no-NO/internationalization_index.md deleted file mode 100644 index 615e351b..00000000 --- a/website/translated_docs/no-NO/internationalization_index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: "Internationalization" ---- - -The Home Assistant internationalization project includes preparing platforms and the frontend for localization, as well as the actual translation of localized strings. - -Some components and platforms will have strings that need to be localized specifically for that platform. These strings are managed in the core [home-assistant](https://github.com/home-assistant/home-assistant) repository. The Home Assistant backend will serve strings to the clients based on the loaded components in the running instance. - -There are also localizable strings that exist only on the frontend. These strings are managed in the [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer) repository. These strings are stored with the frontend and don’t depend on the backend configuration. - -Our strings are translated by the community using the online translation tool [Lokalise](https://lokalise.co/). \ No newline at end of file diff --git a/website/translated_docs/no-NO/internationalization_translation.md b/website/translated_docs/no-NO/internationalization_translation.md deleted file mode 100644 index a6faf7c9..00000000 --- a/website/translated_docs/no-NO/internationalization_translation.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Translation" ---- - -Translations for Home Assistant are managed through [Lokalise](https://lokalise.co/), an online translation management tool. Our translations are split between two projects, a backend project for platform-specific translations, and a frontend project for UI translations. Click the links below to join both projects! Even if your language is completely translated, extra proofreading is a big help! Please feel free to review the existing translations, and vote for alternatives that might be more appropriate. - -- [Join the frontend translation team](https://lokalise.co/signup/3420425759f6d6d241f598.13594006/all/) -- [Join the backend translation team](https://lokalise.co/signup/130246255a974bd3b5e8a1.51616605/all/) -- [Join the iOS translation team](https://lokalise.co/signup/834452985a05254348aee2.46389241/all/) - -For more information about the translation workflow, please see the [Lokalise translation workflow documents](https://docs.lokalise.co/category/iOzEuQPS53-for-team-leads-and-translators). - -> The translation of the Home Assistant frontend is still a work in progress. More phrases will be available for translation soon. - -## Translation placeholders - -Some translation strings will contain special placeholders that will be replaced later. Placeholders shown in square brackets `[]` are [Lokalise key references](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing). These are primarily used to link translation strings that will be duplicated. Different languages may not have the same duplicates as English, and are welcome to link duplicate translations that are not linked in English. Placeholders shown in curly brackets `{}` are [translation arguments](https://formatjs.io/guides/message-syntax/) that will be replaced with a live value when Home Assistant is running. Any translation argument placeholders present in the original string must be included in the translated string. These may include special syntax for defining plurals or other replacement rules. The linked format.js guide explains the syntax for adding plural definitions and other rules. - -## Rules - -1. Only native speakers should submit translations. -2. Stick to [Material Design guidelines](https://material.io/guidelines/style/writing.html). -3. Don't translate or change proper nouns like `Home Assistant`, `Hass.io` or `Hue`. -4. For a region specific translation, keys that will be the same as the base translation should be filled with `[VOID]`. These will be replaced during our translation build process. -5. Translations under the `state_badge` keys will be used for the notification badge display. These translations should be short enough to fit in the badge label without overflowing. This can be tested in the Home Assistant UI either by editing the label text with your browsers development tools, or by using the States states dev tool icon developer tool in the Home Assistant UI. In the UI, enter a new entity ID (`device_tracker.test`), and enter the text you want to test in state. -6. If text will be duplicated across different translation keys, make use of the Lokalise key reference feature where possible. The base translation provides examples of this underneath the `states` translations. Please see the [Lokalise key referencing](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing) documentation for more details. - -## Adding a new language - -If your language is not listed you can request it at [GitHub](https://github.com/home-assistant/home-assistant-polymer/issues/new). Please provide both the English name and the native name for your language. For example: - - English Name: German - Native Name: Deutsch - - -> Region specific translations (`en-US`, `fr-CA`) will only be included if translations for that region need to differ from the base language translation. - -### Maintainer steps to add a new language - -1. Language tags have to follow [BCP 47](https://tools.ietf.org/html/bcp47). A list of most language tags can be found here: [IANA sutbtag registry](http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry). Examples: `fr`, `fr-CA`, `zh-Hans`. Only include the country code if country specific overrides are being included, and the base language is already translated. -2. Add the language tag and native name in `src/translations/translationMetadata.json`. Examples: "Français", "Français (CA)" -3. Add the new language in Lokalize. Note: Sometimes you have to change the tag in Lokalise (Language -> Language settings -> custom ISO code). \ No newline at end of file diff --git a/website/translated_docs/no-NO/lovelace_custom_card.md b/website/translated_docs/no-NO/lovelace_custom_card.md deleted file mode 100644 index 85e89f77..00000000 --- a/website/translated_docs/no-NO/lovelace_custom_card.md +++ /dev/null @@ -1,225 +0,0 @@ ---- -title: "Lovelace: Custom Cards" ---- - -[Lovelace](https://www.home-assistant.io/lovelace/) is our new approach to defining your user interface for Home Assistant. We offer a lot of built-in cards, but you're not just limited to the ones that we decided to include in the Lovelace UI. You can build and use your own! - -## API - -You define your custom card as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). It's up to you to decide how to render your DOM inside your element. You can use Polymer, Angular, Preact or any other popular framework (except for React – [more info on React here](https://custom-elements-everywhere.com/#react)). - -```js -const element = document.createElement('some-custom-card'); -``` - -Home Assistant will call `setConfig(config)` when the configuration changes (rare). If you throw an exception if the configuration is invalid, Lovelace will render an error card to notify the user. - -```js -try { - element.setConfig(config); -} catch (err) { - showErrorCard(err.message, config); -} -``` - -Home Assistant will set the `hass` property when the state of Home Assistant changes (frequent). Whenever the state changes, the component will have to update itself to represent the latest state. - -```js -element.hass = hass; -``` - -Your card can define a `getCardSize` method that returns the size of your card as a number. A height of 1 is equivalent to 50 pixels. This will help Home Assistant distribute the cards evenly over the columns. A card size of `1` will be assumed if the method is not defined. - -```js -if ('getCardSize' in element) { - return element.getCardSize(); -} else { - return 1; -} -``` - -## Defining your card - -Create a new file in your Home Assistant config dir as `/www/content-card-example.js` and put in the following contents: - -```js -class ContentCardExample extends HTMLElement { - set hass(hass) { - if (!this.content) { - const card = document.createElement('ha-card'); - card.header = 'Example card'; - this.content = document.createElement('div'); - this.content.style.padding = '0 16px 16px'; - card.appendChild(this.content); - this.appendChild(card); - } - - const entityId = this.config.entity; - const state = hass.states[entityId]; - const stateStr = state ? state.state : 'unavailable'; - - this.content.innerHTML = ` - The state of ${entityId} is ${stateStr}! -

- - `; - } - - setConfig(config) { - if (!config.entity) { - throw new Error('You need to define an entity'); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return 3; - } -} - -customElements.define('content-card-example', ContentCardExample); -``` - -## Referencing your new card - -In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `/www` directory, it will be accessible in your browser via the url `/local/` (if you have recently added the www folder you will need to re-start Home Assistant for files to be picked up). - -```yaml -# Example Lovelace configuration -resources: - - url: /local/content-card-example.js - type: js -views: -- name: Example - cards: - - type: "custom:content-card-example" - entity: input_boolean.switch_tv -``` - -## Advanced example - -Resources to load in Lovelace can be imported as a JS script, an HTML import or as a JS module import. Below is an example of a custom card using JS modules that does all the fancy things. - -![Screenshot of the wired card](/img/en/frontend/lovelace-ui-custom-card-screenshot.png) - -Create a new file in your Home Assistant config dir as `/www/wired-cards.js` and put in the following contents: - -```js -import "https://unpkg.com/wired-card@0.8.1/wired-card.js?module"; -import "https://unpkg.com/wired-toggle@0.8.0/wired-toggle.js?module"; -import { - LitElement, - html, - css -} from "https://unpkg.com/lit-element@2.0.1/lit-element.js?module"; - -function loadCSS(url) { - const link = document.createElement("link"); - link.type = "text/css"; - link.rel = "stylesheet"; - link.href = url; - document.head.appendChild(link); -} - -loadCSS("https://fonts.googleapis.com/css?family=Gloria+Hallelujah"); - -class WiredToggleCard extends LitElement { - static get properties() { - return { - hass: {}, - config: {} - }; - } - - render() { - return html` - - ${this.config.entities.map(ent => { - const stateObj = this.hass.states[ent]; - return stateObj - ? html` -
- ${stateObj.attributes.friendly_name} - -
- ` - : html` -
Entity ${ent} not found.
- `; - })} -
- `; - } - - setConfig(config) { - if (!config.entities) { - throw new Error("You need to define entities"); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return this.config.entities.length + 1; - } - - _toggle(state) { - this.hass.callService("homeassistant", "toggle", { - entity_id: state.entity_id - }); - } - - static get styles() { - return css` - :host { - font-family: "Gloria Hallelujah", cursive; - } - wired-card { - background-color: white; - padding: 16px; - display: block; - font-size: 18px; - } - .state { - display: flex; - justify-content: space-between; - padding: 8px; - align-items: center; - } - .not-found { - background-color: yellow; - font-family: sans-serif; - font-size: 14px; - padding: 8px; - } - wired-toggle { - margin-left: 8px; - } - `; - } -} -customElements.define("wired-toggle-card", WiredToggleCard); -``` - -And for your configuration: - -```yaml -# Example Lovelace configuration -resources: - - url: /local/wired-cards.js - type: module -views: -- name: Example - cards: - - type: "custom:wired-toggle-card" - entities: - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_livingroom - - input_boolean.switch_tv -``` diff --git a/website/translated_docs/no-NO/lovelace_index.md b/website/translated_docs/no-NO/lovelace_index.md deleted file mode 100644 index 40c4e67d..00000000 --- a/website/translated_docs/no-NO/lovelace_index.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: "Lovelace UI" -sidebar_label: Introduction ---- - -This page has been moved to https://www.home-assistant.io/lovelace/ - - diff --git a/website/translated_docs/no-NO/maintenance.md b/website/translated_docs/no-NO/maintenance.md deleted file mode 100644 index 78b94aac..00000000 --- a/website/translated_docs/no-NO/maintenance.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: "Maintenance" ---- - -This page documents a couple of points for maintaining the Home Assistant code. Most of the tasks don't need to be performed on a regular base thus the steps, used tools, or details are preserved here. - -## Source code - -### Line separator - -People are using various operating systems to develop components and platforms for Home Assistant. This could lead to different line endings on file. We prefer `LN`. Especially Microsoft Windows tools tend to use `CRLF`. - -```bash -$ find homeassistant -name "*.py" -exec file {} \; | grep BOM -$ find homeassistant -name "*.py" -exec file {} \; | grep CRLF -``` - -To fix the line separator, use `dos2unix` or `sed`. - -```bash -$ dos2unix homeassistant/components/notify/kodi.py -``` - -### File permissions - -Most files don't need to the be executable. `0644` is fine. - -### Dependencies - -A lot of components and platforms depends on third-party Python modules. The dependencies which are stored in the `requirements_*.txt` files are tracked by [Requires.io](https://requires.io/github/home-assistant/home-assistant/requirements/?branch=dev). - -If you update the requirements of a component/platform by updating `manifest.json`, run the provided script to update the `requirements_*.txt` file(s). - -```bash -$ script/gen_requirements_all.py -``` - -Start a test run of Home Assistant. If that was successful, include all files in a Pull Request. Add a short summary of the changes, a sample configuration entry, details about the tests you performed to ensure the update works, and other useful information to the description. - -## Documentation - -- Merge `current` into `next` on a regular base. -- Optimize the images. \ No newline at end of file diff --git a/website/translated_docs/no-NO/misc.md b/website/translated_docs/no-NO/misc.md deleted file mode 100644 index 925d2868..00000000 --- a/website/translated_docs/no-NO/misc.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -title: Miscellaneous ---- - -Catch all category. Topics are not related to one another. \ No newline at end of file diff --git a/website/translated_docs/no-NO/releasing.md b/website/translated_docs/no-NO/releasing.md deleted file mode 100644 index dc56665b..00000000 --- a/website/translated_docs/no-NO/releasing.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: "Releasing" ---- - -This page describes the steps for publishing a new Home Assistant release. Those steps requires that you don't use forks but work with the repositories themself. The [hass-release](https://github.com/home-assistant/hass-release) script is a helper to do a release. - -### Release preparation (3 days before release) - -### GitHub - -1. Merge `master` into `dev` to make the PR mergeable. -2. Cut a release branch from `dev`. Example name `release-0-57`. -3. Create a pull request from the release branch to `master` with the upcoming release number as the title. -4. Update `homeassistant/const.py` with the correct version number (remove the `dev` tag) and push that commit to release branch. - -### Website - -1. Merge `current` into `next` -2. Cut release branch of `next`. For example `release-0-57`. -3. Open a PR from release branch to `current` with the upcoming release number as the title. - -## Release day - -From creating the release branch till it has been merged, we tag bugfixes with the milestone for the release (create if doesn't exist). - -### GitHub - -1. Cherry-pick the milestoned PRs that need to get into the release `python3 -m hassrelease milestone_cherry_pick 0.57` -2. Run `python3 -m hassrelease release_notes 0.56` for the release notes. -3. Once the release notes has been generated, issue `python3 -m hassrelease milestone_close 0.56` -4. Merge pull request (DO NOT SQUASH!). Use `Merge pull request`. -5. Go to [releases](https://github.com/home-assistant/home-assistant/releases), click `Draft a new release` and tag a new release on the `master` branch. "Tag version" and "Release title" are the version number (`O.x` for major version, `0.x.y` for minor and bug fix releases). Release description is the text from PR. Press "Publish release" to finish the process. -6. Merge `master` into `dev`. -7. Update `homeassistant/const.py` with the upcoming version number (including the `dev` tag) and push that commit to the `dev` branch. - -### Website - -1. Create a blog post in the release branch and base it on the text of the PR in the main repository. Add images, additional text, links, etc. if it adds value. Tag each platform/component in a message to documentation. -2. Create missing documentation as stubs. -3. Run `credits_generator`. -4. Update `_config.yml` with a link to the new release blog post and version number (at the bottom of the file). -5. Merge `current` into release branch (`$ git checkout release-0-40 && git merge current`) to make the PR mergeable. -6. Merge pull request (blog post, updated frontpage, and all new documentation) to `current`. DO NOT SQUASH! -7. Merge `current` into `next`. - -### Docker Hub - -Tags on Docker hub are automatically created when a release has been created on GitHub. - -### Python Package Index - -Checkout the `master` branch and run `script/release` to publish the new release on [Python Package Index](https://pypi.python.org). - -### Social media - -1. Use [hootsuite](https://hootsuite.com/dashboard) to publish a link to the release post on social media. - -## Bugfix Release - -1. Checkout `master` and update it. `git checkout master && git pull --rebase` -2. Create a new release branch from `master`. `git checkout -b release-0-56-2` -3. Cherry-pick the PRs which were milestoned. -4. Update `homeassistant/const.py` with the correct version number (increment `PATCH_VERSION`) and push that commit to release branch. -5. Create a pull request from the release branch to `master` with the upcoming release number as the title. -6. Merge pull request (DO NOT SQUASH!). Use `Merge pull request`. -7. Go to [releases](https://github.com/home-assistant/home-assistant/releases), click `Draft a new release` and tag a new release on the `master` branch. "Tag version" and "Release title" are the version number (`O.x` for major version, `0.x.y` for minor and bug fix releases). Release description is the text from PR. Press "Publish release" to finish the process. -8. Publish the new release on PyPI. \ No newline at end of file diff --git a/website/translated_docs/pl/app_integration_index.md b/website/translated_docs/pl/app_integration_index.md deleted file mode 100644 index 8a181840..00000000 --- a/website/translated_docs/pl/app_integration_index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: "Native App Integration" -sidebar_label: "Introduction" ---- - -This guide describes how to build a native Home Assistant app that communicates with Home Assistant and offers a seamless integration. Below is a list of the things that we will discuss in this guide. - -- Allow the user to establish a connection and authenticate with their own Home Assistant instance. -- Send location and device info back to Home Assistant. -- Call services, fire events and render templates. -- A view to control the house via an authenticated webview. \ No newline at end of file diff --git a/website/translated_docs/pl/app_integration_notifications.md b/website/translated_docs/pl/app_integration_notifications.md deleted file mode 100644 index a4861554..00000000 --- a/website/translated_docs/pl/app_integration_notifications.md +++ /dev/null @@ -1,235 +0,0 @@ ---- -title: "Push Notifications" ---- - -The `mobile_app` component has a notify platform built in that allows for a generic way to send push notifications to your users without requiring installation of a external custom component. - -## Enabling push notifications - -To enable the notify platform for your application, you must set two keys in the `app_data` object during the initial registration or later update of an existing registration. - -| Key | Type | Description | -| ------------ | ------ | -------------------------------------------------------------------------------------------------------------------------- | -| `push_token` | string | A push notification token unique to your users device. For example, this could be a APNS token or a FCM Instance ID/token. | -| `push_url` | string | The URL on your server that push notifications will be HTTP POSTed to. | - -You should advise the user to restart Home Assistant after you set these keys in order for them to see the notify target. It will have the format `notify.mobile_app_`. - -## Deploying a server component - -The notify platform doesn't concern itself with how to notify your users. It simply forwards a notification to your external server where you should actually handle the request. This approach allows you to maintain full control over your push notification infrastructure. - -See the next section of this document for an example server implementation of a push notification forwarder that uses Firebase Cloud Functions and Firebase Cloud Messaging. - -Your server should accept a HTTP POST payload like this: - -```json -{ - "message": "Hello World", - "title": "Test message sent via mobile_app.notify", - "push_token": "my-secure-token", - "registration_info": { - "app_id": "io.home-assistant.iOS", - "app_version": "1.0.0", - "os_version": "12.2" - }, - "data": { - "key": "value" - } -} -``` - -It should respond with a 201 status code assuming the notification was queued for delivery successfully. - -### Errors - -If an error occurs you should return a description of what went wrong with a status code *other than* 201 or 429. An error response must be a JSON object and can contain one of the following keys: - -| Key | Type | Description | -| -------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `errorMessage` | string | If provided, it will be appended to a preset error message. For example, if `errorMessage` is "Could not communicate with Apple" it will be output in the log like "Internal server error, please try again later: Could not communicate with Apple" | -| `message` | string | If provided, it will be output directly to the logs at the warning log level. | - -No matter what key you use, you should try to be as descriptive as possible about what went wrong and, if possible, how the user can fix it. - -### Rate limits - -The notify platform also supports exposing rate limits to users. Home Assistant suggests you implement a conservative rate limit to keep your costs low and also so that users don't overload themselves with too many notifications. For reference, Home Assistant Companion has a maximum sendable notifications per 24 hours of 150 notifications. The rate limit resets for all users at midnight, UTC. You of course are free to use whatever configuration for your own rate limiting. - -If you choose to implement rate limiting, your successful server response should look like the following: - -```json -{ - "rateLimits": { - "successful": 1, - "errors": 5, - "maximum": 150, - "resetsAt": "2019-04-08T00:00:00.000Z" - } -} -``` - -| Key | Type | Description | -| ------------ | ----------------- | ------------------------------------------------------------------------------------------------ | -| `successful` | integer | The number of successful push notifications the user has sent during the rate limit period. | -| `errors` | integer | The number of failed push notifications the user has sent during the rate limit period. | -| `maximum` | integer | The maximum number of push notifications the user can send during the users rate limit period. | -| `resetsAt` | ISO8601 timestamp | The timestamp that the users rate limit period expires at. Must be provided in the UTC timezone. | - -The rate limits will be output to the log at the warning log level after every notification is successfully sent. Home Assistant will also output the exact time remaining until the rate limit period resets. - -Once the user hits their maximum amount of notifications sent in the rate limit period, you should start responding with a 429 status code until the rate limit period expires. The response object can optionally contain a key, `message` which will be output to the Home Assistant log instead of the standard error message. - -The notify platform does not itself implement any kind of rate limit protections. Users will be able to keep sending you notifications, so you should reject them with a 429 status code as early in your logic as possible. - -## Example server implementation - -The below code is a Firebase Cloud Function that forwards notifications to Firebase Cloud Messaging. To deploy this, you should create a new Firestore database named `rateLimits`. Then, you can deploy the following code. Also, ensure that you have properly configured your project with the correct authentication keys for APNS and FCM. - -```javascript -'use strict'; - -const functions = require('firebase-functions'); -const admin = require('firebase-admin'); -admin.initializeApp(); - -var db = admin.firestore(); - -const MAX_NOTIFICATIONS_PER_DAY = 150; - -exports.sendPushNotification = functions.https.onRequest(async (req, res) => { - console.log('Received payload', req.body); - var today = getToday(); - var token = req.body.push_token; - var ref = db.collection('rateLimits').doc(today).collection('tokens').doc(token); - - var payload = { - notification: { - body: req.body.message, - }, - token: token, - }; - - if(req.body.title) { - payload.notification.title = req.body.title; - } - - if(req.body.data) { - if(req.body.data.android) { - payload.android = req.body.data.android; - } - if(req.body.data.apns) { - payload.apns = req.body.data.apns; - } - if(req.body.data.data) { - payload.data = req.body.data.data; - } - if(req.body.data.webpush) { - payload.webpush = req.body.data.webpush; - } - } - - console.log('Notification payload', JSON.stringify(payload)); - - var docExists = false; - var docData = { - deliveredCount: 0, - errorCount: 0, - totalCount: 0, - }; - - try { - let currentDoc = await ref.get(); - docExists = currentDoc.exists; - if(currentDoc.exists) { - docData = currentDoc.data(); - } - } catch(err) { - console.error('Error getting document!', err); - return handleError(res, 'getDoc', err); - } - - if(docData.deliveredCount > MAX_NOTIFICATIONS_PER_DAY) { - return res.status(429).send({ - errorType: 'RateLimited', - message: 'The given target has reached the maximum number of notifications allowed per day. Please try again later.', - target: token, - rateLimits: getRateLimitsObject(docData), - }); - } - - docData.totalCount = docData.totalCount + 1; - - var messageId; - try { - messageId = await admin.messaging().send(payload); - docData.deliveredCount = docData.deliveredCount + 1; - } catch(err) { - docData.errorCount = docData.errorCount + 1; - await setRateLimitDoc(ref, docExists, docData, res); - return handleError(res, 'sendNotification', err); - } - - console.log('Successfully sent message:', messageId); - - await setRateLimitDoc(ref, docExists, docData, res); - - return res.status(201).send({ - messageId: messageId, - sentPayload: payload, - target: token, - rateLimits: getRateLimitsObject(docData), - }); - -}); - -async function setRateLimitDoc(ref, docExists, docData, res) { - try { - if(docExists) { - console.log('Updating existing doc!'); - await ref.update(docData); - } else { - console.log('Creating new doc!'); - await ref.set(docData); - } - } catch(err) { - if(docExists) { - console.error('Error updating document!', err); - } else { - console.error('Error creating document!', err); - } - return handleError(res, 'setDocument', err); - } - return true; -} - -function handleError(res, step, incomingError) { - if (!incomingError) return null; - console.error('InternalError during', step, incomingError); - return res.status(500).send({ - errorType: 'InternalError', - errorStep: step, - message: incomingError.message, - }); -} - -function getToday() { - var today = new Date(); - var dd = String(today.getDate()).padStart(2, '0'); - var mm = String(today.getMonth() + 1).padStart(2, '0'); - var yyyy = today.getFullYear(); - return yyyy + mm + dd; -} - -function getRateLimitsObject(doc) { - var d = new Date(); - return { - successful: (doc.deliveredCount || 0), - errors: (doc.errorCount || 0), - total: (doc.totalCount || 0), - maximum: MAX_NOTIFICATIONS_PER_DAY, - remaining: (MAX_NOTIFICATIONS_PER_DAY - doc.deliveredCount), - resetsAt: new Date(d.getFullYear(), d.getMonth(), d.getDate()+1) - }; -} -``` \ No newline at end of file diff --git a/website/translated_docs/pl/app_integration_sending_data.md b/website/translated_docs/pl/app_integration_sending_data.md deleted file mode 100644 index eebab867..00000000 --- a/website/translated_docs/pl/app_integration_sending_data.md +++ /dev/null @@ -1,228 +0,0 @@ ---- -title: "Sending data home" ---- - -Once you have registered your app with the mobile app component, you can start interacting with Home Assistant via the provided webhook information. - -The first step is to turn the returned webhook ID into a full URL: `/api/webhook/`. This will be the only url that we will need for all our interactions. The webhook endpoint will not require authenticated requests. - -If you were provided a Cloudhook URL during registration, you should use that by default and only fall back to a constructed URL as described above if that request fails. - -If you were provided a remote UI URL during registration, you should use that as the `instance_url` when constructing a URL and only fallback to the user provided URL if the remote UI URL fails. - -To summarize, here's how requests should be made: - -1. If you have a Cloudhook URL, use that until a request fails. When a request fails, go to step 2. -2. If you have a remote UI URL, use that to construct a webhook URL: `/api/webhook/`. When a request fails, go to step 3. -3. Construct a webhook URL using the instance URL provided during setup: `/api/webhook/`. - -## Short note on instance URLs - -Some users have configured Home Assistant to be available outside of their home network using a dynamic DNS service. There are some routers that don't support hairpinning / NAT loopback: a device sending data from inside the routers network, via the externally configured DNS service, to Home Asisstant, which also resides inside the local network. - -To work around this, the app should record which WiFi SSID is the users home network, and use a direct connection when connected to the home WiFi network. - -## Interaction basics - -### Request - -All interaction will be done by making HTTP POST requests to the webhook url. These requests do not need to contain authentication. - -The payload format depends on the type of interaction, but it all shares a common base: - -```json5 -{ - "type": "", - "data": {} -} -``` - -If you received a `secret` during registration, you **MUST** encrypt your message and put it in the payload like this: - -```json5 -{ - "type": "encrypted", - "encrypted": true, - "encrypted_data": "" -} -``` - -### Response - -As a general rule, expect to receive a 200 response for all your requests. There are a few cases in which you will receive another code: - -- You will receive a 400 status code if your JSON is invalid. However, you will not receive this error if the encrypted JSON is invalid. -- You will receive a 201 when creating a sensor -- If you receive a 404, the `mobile_app` component most likely isn't loaded. -- Receiving a 410 means the integration has been deleted. You should notify the user and most likely register again. - -## Implementing encryption - -`mobile_app` supports two way encrypted communication via [Sodium](https://libsodium.gitbook.io/doc/). - -> Sodium is a modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more. - -### Choosing a library - -Libraries that wrap Sodium exist for most modern programming languages and platforms. Sodium itself is written in C. - -Here are the libraries we suggest using, although you should feel free to use whatever works well for you. - -- Swift/Objective-C: [swift-sodium](https://github.com/jedisct1/swift-sodium) (official library maintained by Sodium developers. - -For other languages, please see the list of [Bindings for other languages](https://download.libsodium.org/doc/bindings_for_other_languages). If more than one choice is available, we recommend using the choice most recently updated. - -### Configuration - -We use the [secret-key cryptography](https://download.libsodium.org/doc/secret-key_cryptography) features of Sodium to encrypt and decrypt payloads. All payloads are JSON encoded in Base64. For Base64 type, use `sodium_base64_VARIANT_ORIGINAL` (that is, "original", no padding, not URL safe). - -### Signaling encryption support - -During registration, you must set `supports_encryption` to `true` to enable encryption. The Home Assistant instance must be able to install `libsodium` to enable encryption. Confirm that you should make all future webhook requests encrypted by the presence of the key `secret` in the initial registration response. You must store this secret forever. There is no way to recover it via the Home Assistant UI and you should **not** ask users to investigate hidden storage files to re-enter the encryption key. You should create a new registration if encryption ever fails and alert the user. - -## Update device location - -This message will inform Home Assistant of new location information. - -```json -{ - "type": "update_location", - "data": { - "gps": [12.34, 56.78], - "gps_accuracy": 120, - "battery": 45 - } -} -``` - -| Key | Type | Description | -| ------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------- | -| `location_name` | string | Name of the zone the device is in. | -| `gps` | latlong | Current location as latitude and longitude. | -| `gps_accuracy` | int | GPS accurracy in meters. Must be greater than 0. | -| `battery` | int | Percentage of battery the device has left. Must be greater than 0. | -| `speed` | int | Speed of the device in meters per second. Must be greater than 0. | -| `altitude` | int | Altitude of the device in meters. Must be greater than 0. | -| `course` | int | The direction in which the device is traveling, measured in degrees and relative to due north. Must be greater than 0. | -| `vertical_accuracy` | int | The accuracy of the altitude value, measured in meters. Must be greater than 0. | - -## Call a service - -Call a service in Home Assistant. - -```json -{ - "type": "call_service", - "data": { - "domain": "light", - "service": "turn_on", - "service_data": { - "entity_id": "light.kitchen" - } - } -} -``` - -| Key | Type | Description | -| -------------- | ------ | ------------------------------- | -| `domain` | string | The domain of the service | -| `service` | string | The service name | -| `service_data` | dict | The data to send to the service | - -## Fire an event - -Fire an event in Home Assistant. - -```json -{ - "type": "fire_event", - "data": { - "event_type": "my_custom_event", - "event_data": { - "something": 50 - } - } -} -``` - -| Key | Type | Description | -| ------------ | ------ | ------------------------- | -| `event_type` | string | Type of the event to fire | -| `event_data` | string | Date of the event to fire | - -## Render templates - -Renders one or more templates and returns the result(s). - -```json -{ - "type": "render_template", - "data": { - "my_tpl": { - "template": "Hello {{ name }}, you are {{ states('person.paulus') }}.", - "variables": { - "name": "Paulus" - } - } - } -} -``` - -`data` must contain a map of `key`: `dictionary`. Results will be returned like `{"my_tpl": "Hello Paulus, you are home"}`. This allows for rendering multiple templates in a single call. - -| Key | Type | Description | -| ----------- | ------ | ---------------------------------------- | -| `template` | string | The template to render | -| `variables` | Dict | The extra template variables to include. | - -## Update registration - -Update your app registration. Use this if the app version changed or any of the other values. - -```json -{ - "type": "update_registration", - "data": { - "app_data": { - "push_token": "abcd", - "push_url": "https://push.mycool.app/push" - }, - "app_version": "2.0.0", - "device_name": "Robbies iPhone", - "manufacturer": "Apple, Inc.", - "model": "iPhone XR", - "os_version": "23.02" - } -} -``` - -All keys are optional. - -| Key | Type | Description | -| -------------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------- | -| `app_data` | Dict | App data can be used if the app has a supporting component that extends mobile_app functionality or wishes to enable the notification platform. | -| `app_version` | string | Version of the mobile app. | -| `device_name` | string | Name of the device running the app. | -| `manufacturer` | string | The manufacturer of the device running the app. | -| `model` | string | The model of the device running the app. | -| `os_version` | string | The OS version of the device running the app. | - -## Get zones - -Get all enabled zones. - -```json -{ - "type": "get_zones" -} -``` - -## Get config - -Returns a version of `/api/config` with values useful for configuring your app. - -```json -{ - "type": "get_config" -} -``` \ No newline at end of file diff --git a/website/translated_docs/pl/app_integration_sensors.md b/website/translated_docs/pl/app_integration_sensors.md deleted file mode 100644 index 08a30ce9..00000000 --- a/website/translated_docs/pl/app_integration_sensors.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "Sensors" ---- - -The `mobile_app` component supports exposing custom sensors that can be managed entirely via your app. - -## Registering a sensor - -All sensors must be registered before they can get updated. You can only register one sensor at a time, unlike updating sensors. - -To register a sensor, make a request to the webhook like this: - -```json -{ - "data": { - "attributes": { - "foo": "bar" - }, - "device_class": "battery", - "icon": "mdi:battery", - "name": "Battery State", - "state": "12345", - "type": "sensor", - "unique_id": "battery_state", - "unit_of_measurement": "%" - }, - "type": "register_sensor" -} -``` - -The valid keys are: - -| Key | Type | Required | Description | -| --------------------- | ----------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| attributes | object | No | Attributes to attach to the sensor | -| device_class | string | No | One of the valid device classes. [Binary Sensor Classes](https://www.home-assistant.io/components/binary_sensor/#device-class), [Sensor Classes](https://www.home-assistant.io/components/sensor/#device-class) | -| icon | Material Design Icon (string) | No | Must be prefixed `mdi:`. If not provided, default value is `mdi:cellphone` | -| name | string | Yes | The name of the sensor | -| state | bool, float, int, string | Yes | The state of the sensor | -| type | string | Yes | The type of the sensor. Must be one of `binary_sensor` or `sensor` | -| unique_id | string | Yes | A identifier unique to this installation of your app. You'll need this later. Usually best when its a safe version of the sensor name | -| unit_of_measurement | string | No | The unit of measurement for the sensor | - -Sensors will appear as soon as they are registered. - -## Updating a sensor - -Once a sensor has been registered, you need to update it. This is very similar to registering it, but you can update all your sensors at the same time. - -For example, to update the sensor we registered above, you would send this: - -```json -{ - "data": [ - { - "attributes": { - "hello": "world" - }, - "icon": "mdi:battery", - "state": 123, - "type": "sensor", - "unique_id": "battery_state" - } - ], - "type": "update_sensor_states" -} -``` - -Only some of the keys are allowed during updates: - -| Key | Type | Required | Description | -| ---------- | ----------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------- | -| attributes | object | No | Attributes to attach to the sensor | -| icon | Material Design Icon (string) | No | Must be prefixed `mdi:` | -| state | bool, float, int, string | Yes | The state of the sensor | -| type | string | Yes | The type of the sensor. Must be one of `binary_sensor` or `sensor` | -| unique_id | string | Yes | A identifier unique to this installation of your app. You'll need this later. Usually best when its a safe version of the sensor name | \ No newline at end of file diff --git a/website/translated_docs/pl/app_integration_setup.md b/website/translated_docs/pl/app_integration_setup.md deleted file mode 100644 index efd3a03b..00000000 --- a/website/translated_docs/pl/app_integration_setup.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: "Connecting to an instance" ---- - -When a user first opens the app, they will need to connect to their local instance to authenticate and register the device. - -## Authenticating the user - -The local instance can be discovered if Home Assistant has the [zeroconf component](https://www.home-assistant.io/components/zeroconf) configured by searching for `_home-assistant._tcp.local.`. If not configured, the user will need to be asked for the local address of their instance. - -When the address of the instance is known, the app will ask the user to authenticate via [OAuth2 with Home Assistant](auth_api.md). Home Assistant uses IndieAuth, which means that to be able to redirect to a url that triggers your app, you need to take some extra steps. Make sure to read the last paragraph of the "Clients" section thoroughly. - -## Registering the device - -*This requires Home Assistant 0.90 or later.* - -Home Assistant has a `mobile_app` component that allows applications to register themselves and interact with the instance. This is a generic component to handle most common mobile application tasks. This component is extendable with custom interactions if your app needs more types of interactions than are offered by this component. - -Once you have tokens to authenticate as a user, it's time to register the app with the mobile app component in Home Assistant. - -### Getting Ready - -First, you must ensure that the `mobile_app` component is loaded. There are two ways to do this: - -- You can publish a Zeroconf/Bonjour record `_hass-mobile-app._tcp.local.` to trigger the automatic load of the `mobile_app` component. You should wait at least 60 seconds after publishing the record before continuing. -- You can ask the user to add `mobile_app` to their configuration.yaml and restart Home Assistant. If the user already has `default_config` in their configuration, then `mobile_app` will have been already loaded. - -You can confirm the `mobile_app` component has been loaded by checking the `components` array of the [`/api/config` REST API call](external_api_rest.md#get-api-config). If you continue to device registration and receive a 404 status code, then it most likely hasn't been loaded yet. - -### Registering the device - -To register the device, make an authenticated POST request to `/api/mobile_app/registrations`. [More info on making authenticated requests.](auth_api.md#making-authenticated-requests) - -Example payload to send to the registration endpoint: - -```json -{ - "app_id": "awesome_home", - "app_name": "Awesome Home", - "app_version": "1.2.0", - "device_name": "Robbies iPhone", - "manufacturer": "Apple, Inc.", - "model": "iPhone X", - "os_version": "iOS 10.12", - "supports_encryption": true, - "app_data": { - "push_notification_key": "abcdef", - } -} -``` - -| Key | Required | Type | Description | -| --------------------- | -------- | ------ | --------------------------------------------------------------------------------------------------- | -| `app_id` | V | string | A unique identifier for this app. | -| `app_name` | V | string | Name of the mobile app. | -| `app_version` | V | string | Version of the mobile app. | -| `device_name` | V | string | Name of the device running the app. | -| `manufacturer` | V | string | The manufacturer of the device running the app. | -| `model` | V | string | The model of the device running the app. | -| `os_version` | V | string | The OS version of the device running the app. | -| `supports_encryption` | V | bool | If the app supports encryption. See also the [encryption section](#encryption). | -| `app_data` | | Dict | App data can be used if the app has a supporting component that extends `mobile_app` functionality. | - -When you get a 200 response, the mobile app is registered with Home Assistant. The response is a JSON document and will contain the URLs on how to interact with the Home Assistant instance. You should permanently store this information. - -```json -{ - "cloudhook_url": "https://hooks.nabu.casa/randomlongstring123", - "remote_ui_url": "https://randomlongstring123.ui.nabu.casa", - "secret": "qwerty", - "webhook_id": "abcdefgh" -} -``` - -| Key | Type | Description | -| --------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `cloudhook_url` | string | The cloudhook URL provided by Home Assistant Cloud. Only will be provided if user is actively subscribed to Nabu Casa. | -| `remote_ui_url` | string | The remote UI URL provided by Home Assistant Cloud. Only will be provided if user is actively subscribed to Nabu Casa. | -| `secret` | string | The secret to use for encrypted communication. Will only be included if encryption is supported by both the app and the Home Assistant instance. [More info](app_integration_sending_data.md#implementing-encryption). | -| `webhook_id` | string | The webhook ID that can be used to send data back. | \ No newline at end of file diff --git a/website/translated_docs/pl/app_integration_webview.md b/website/translated_docs/pl/app_integration_webview.md deleted file mode 100644 index 82bc53d8..00000000 --- a/website/translated_docs/pl/app_integration_webview.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Authenticated Webview" ---- - -Your application already asked the user to authenticate. This means that your app should not ask the user to authenticate again when they open the Home Assistant UI. - -To make this possible, the Home Assistant UI supports [external authentication](frontend_external_auth). This allows your app to provide hooks so that the frontend will ask your app for access tokens. - -Note that this feature requires a direct connection to the instance. \ No newline at end of file diff --git a/website/translated_docs/pl/architecture_components.md b/website/translated_docs/pl/architecture_components.md deleted file mode 100644 index a1031012..00000000 --- a/website/translated_docs/pl/architecture_components.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Components Architecture" -sidebar_label: "Components" ---- - -Home Assistant can be extended with **components**. Each component is responsible for a specific domain within Home Assistant. Components can listen for or trigger events, offer services, and maintain states. Components are written in Python and can do all the goodness that Python has to offer. Out of the box, Home Assistant offers a bunch of [built-in components](https://www.home-assistant.io/components/). - -Diagram showing interaction between components and the Home Assistant core. - -There are two types of components within Home Assistant: components that interact with an Internet of Things domain, and components that respond to events that happen within Home Assistant. Read on to learn about each type! - -## Components that interact with an Internet-of-Things domain - -These components track devices within a specific domain and consist of a core part and platform-specific logic. These components make their information available via the State Machine and the Event Bus. The components also register services in the Service Registry to expose control of the devices. - -For example, the built-in [`switch` component](https://www.home-assistant.io/components/switch/) is responsible for interaction with different types of switches. A platform provides support for a particular kind or brand of device. For example, a switch could use a WeMo or Orvibo platform and a light component might interact with the Hue or LIFX platform. - -If you want to add support for a new platform, check out the [add new platform section](creating_platform_index.md). - -## Components that respond to events that happen within Home Assistant - -These components provide small pieces of home automation logic or involve services that do common tasks within your house. - -For example, the [`device_sun_light_trigger` component](https://www.home-assistant.io/components/device_sun_light_trigger/) tracks the state of devices and the sun to make sure that the lights are turned on when it gets dark and people are home. The component uses logic like this: - -```text -In the event that device 'Paulus Nexus 5' changes to the 'Home' state: - If the sun has set and the lights are not on: - Turn on the lights -``` - -```text -In the event that the combined state of all tracked devices changes to 'Not Home': - If the lights are on: - Turn off the lights -``` - -```text -In the event of the sun setting: - If the lights are off and the combined state of all tracked device equals 'Home': - Turn on the lights -``` - -## The full picture - -When we put all the different pieces of Home Assistant together, it's a close match for the initial home automation overview sketch. The smart home AI has not been implemented yet, so it's not included in this picture. - -![Overview of the full Home Assistant architecture with a couple of loaded components and platforms](/img/en/architecture/ha_full_architecture.png) - -The platform logic for components uses third-party Python libraries to communicate with the devices. Through this, we can leverage some of the best libraries in the Python community. \ No newline at end of file diff --git a/website/translated_docs/pl/architecture_entities.md b/website/translated_docs/pl/architecture_entities.md deleted file mode 100644 index 82535365..00000000 --- a/website/translated_docs/pl/architecture_entities.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Entity Architecture" -sidebar_label: Entity ---- - -![Architecture overview of Hass.io](/img/en/architecture/entities_architecture.png) - -## Configuration - -Configuration is provided by the [configuration.yaml file](configuration_yaml_index.md) or by a [Config Entry](config_entries_index.md). - -## Component - -Examples of components: `light`, `switch`. - -The component is responsible for defining the Abstract Entity Class and services to control the entities. - -## Entity Component - -The Entity Component is responsible for: - -- Distributing the configuration to the platforms -- Forward config entries and discoveries -- Collect entities for service calls -- Optionally maintain a group of all entities - -## Entity Platform - -The Entity Platform manages all entities for the platform and polls them for updates if necessary. - -When adding entities, the Entity Platform will query the Entity Registry to make sure that the entities to be added have the correct entity IDs. - -## Entity Registry - -The [Entity Registry](entity_registry_index.md) will track entities and allows users to store extra settings for an entity. - -## Platform - -Examples of platforms: `light.hue`, `switch.wemo`. - -Platform uses configuration to query the external device/service and add entities to the entity platform. \ No newline at end of file diff --git a/website/translated_docs/pl/architecture_hassio.md b/website/translated_docs/pl/architecture_hassio.md deleted file mode 100644 index df33383a..00000000 --- a/website/translated_docs/pl/architecture_hassio.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: "Hass.io Architecture" -sidebar_label: Hass.io ---- - -![Architecture overview of Hass.io](/img/en/architecture/hassio.png) - -## Host Control (HC) - -This is a daemon running on the host machine that allows the supervisor to control certain aspects of the host OS: - -- Power cycle (restart, turn off) -- Manage network settings -- Local updates - -## Host - -Our pre-build images are based on [HassOS](https://github.com/home-assistant/hassos) which is based on [BuildRoot](https://buildroot.org/). Any Linux machine can be turned into a Hass.io host by running [the installer](https://www.home-assistant.io/hassio/installation/#alternative-install-on-generic-linux-server). - -## Supervisor - -The supervisor offers an API to manage the host and running the Docker containers. - -## Configuration panel - -The configuration panel lives inside the supervisor but is accessible via the Home Assistant user interface. The configuration panel allows the user to manage the installation. \ No newline at end of file diff --git a/website/translated_docs/pl/architecture_index.md b/website/translated_docs/pl/architecture_index.md deleted file mode 100644 index 550a818d..00000000 --- a/website/translated_docs/pl/architecture_index.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: "Architecture" -sidebar_label: "Introduction" ---- - -Before we dive into the Home Assistant architecture, let's get a clear overview of the home automation landscape as a whole. This way, we can show how the different parts of Home Assistant fit into the picture. - -For more information about each part in this overview, [check out our blog](https://www.home-assistant.io/blog/2014/12/26/home-control-home-automation-and-the-smart-home/). Here's the tl;dr version of the blog: - -- Home Control is responsible for collecting information and controlling devices. -- Home Automation triggers commands based on user configurations. -- Smart Home triggers commands based on previous behavior. - -![Home Automation landscape](/img/en/architecture/home_automation_landscape.svg) - -The Home Assistant core is responsible for Home Control. Home Assistant contains four parts which make this possible: - -- **Event Bus**: facilitates the firing and listening of events -- the beating heart of Home Assistant. -- **State Machine**: keeps track of the states of things and fires a `state_changed` event when a state has been changed. -- **Service Registry**: listens on the event bus for `call_service` events and allows other code to register services. -- **Timer**: sends a `time_changed` event every 1 second on the event bus. - -![Overview of the Home Assistant core architecture](/img/en/architecture/ha_architecture.svg) \ No newline at end of file diff --git a/website/translated_docs/pl/area_registry_index.md b/website/translated_docs/pl/area_registry_index.md deleted file mode 100644 index faf0d208..00000000 --- a/website/translated_docs/pl/area_registry_index.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Area Registry -sidebar_label: Introduction ---- - -The area registry is a registry where Home Assistant keeps track of areas. An area represents a physical location for Home Assistant. It can be used to place devices in different areas. - -| Attribute | Description | -| --------- | ----------------------------------------------- | -| id | Unique ID of area (generated by Home Assistant) | -| name | Name of this area | \ No newline at end of file diff --git a/website/translated_docs/pl/asyncio_101.md b/website/translated_docs/pl/asyncio_101.md deleted file mode 100644 index 3ffc7dd7..00000000 --- a/website/translated_docs/pl/asyncio_101.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: "Asyncio 101" ---- - -If you are not familiar yet with asyncio, please watch the below video. It's a great introduction by [Robert Smallshire](https://github.com/rob-smallshire) in how and why asyncio works the way it does. - -
- -
diff --git a/website/translated_docs/pl/asyncio_categorizing_functions.md b/website/translated_docs/pl/asyncio_categorizing_functions.md deleted file mode 100644 index 71e8206d..00000000 --- a/website/translated_docs/pl/asyncio_categorizing_functions.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: "Categorizing Functions" ---- - -A piece of work within Home Assistant is represented by a function that will be invoked. It will either run inside our event loop or inside our thread pool, depending on if it is async safe. - -Home Assistant uses the convention that all functions that must be run from within the event loop are prefixed with `async_`. - -## The coroutine function - -Coroutines are special functions based on Python’s generators syntax which allows them to suspend execution while waiting on a result. - -Invoking a coroutine function will return a Generator object back, but will not actually begin execution. This object will execute the task when it is either yielded from (from within another coroutine) or it is scheduled on the event loop. - -To declare a function a coroutine, import the coroutine annotation from the asyncio package and annotate your function. - -```python -async def async_look_my_coroutine(target): - result = await entity.async_turn_on() - if result: - print("hello {}".format(target)) - -hass.loop.create_task(async_look_my_coroutine("world")) -``` - -In this example, we schedule the coroutine by calling `hass.loop.create_task`. This will add the coroutine to the queue of tasks to be run. When the event loop is running `async_look_my_coroutine` it will suspend the task when `await entity.async_turn_on()` is called. At that point a new task will be scheduled to execute `entity.async_turn_on()`. When that job has been executed, `async_look_my_coroutine` will resume. - -## The callback function - -This is a normal function that is considered safe to be run from within the event loop. A callback is unable to suspend itself and thus cannot do any I/O or call a coroutine. A callback is capable of scheduling a new task but it will not be able to wait for the results. - -To declare a function as a callback, import the callback annotation from the core package and annotate your function. - -A common use case for a callback in Home Assistant is as a listener for an event or a service call. It can process the incoming information and then schedule the right calls to be made. Example from the automation component. - -```python -from homeassistant.core import callback - -@callback -def async_trigger_service_handler(service_call): - """Handle automation trigger service calls.""" - vars = service_call.data.get(ATTR_VARIABLES) - for entity in component.async_extract_from_service(service_call): - hass.loop.create_task(entity.async_trigger(vars, True)) -``` - -In this example, `entity.async_trigger` is a coroutine function. Invoking the coroutine function will return a coroutine task. The passed in parameters will be used when the task gets executed. - -To execute the task we have to schedule it for execution on the event loop. This is done by calling `hass.loop.create_task`. - -### Why even have callbacks? - -You might wonder, if a coroutine can do everything a callback can do, why even have a callback. The reason is performance and better state consistency of the core API objects. - -When coroutine A waits for coroutine B, it will suspend itself and schedule a new task to run B. This means that the event loop is now running A, B and then A again. If B is a callback, A will never have to suspend itself and thus the event loop is just running A. The consistency implication is that other events queued to run on the event loop continue to wait until callbacks complete, but will be interleaved when yielding to another coroutine. - -## Event loop and thread safe - -These are functions that are safe to run both in a thread and inside the event loop. These functions are usually performing a computation or transform data in memory. Anything that does I/O does not fall under this category. Many standard library functions fall in this category. For example generating the sum of a set of numbers using sum or merging two dictionaries. - -There is no special annotation to mark functions as part of this category and care should be taken when using these functions from inside the event loop. When in doubt, look at their implementation. - -## Other functions - -These are all the functions that did not fit in the previous categories. These functions are either thread-safe or not considered safe to be run within the event loop. These are functions that use sleep, or perform I/O. - -There is no special annotation necessary to be considered part of this category. \ No newline at end of file diff --git a/website/translated_docs/pl/asyncio_index.md b/website/translated_docs/pl/asyncio_index.md deleted file mode 100644 index 6dd2ecaa..00000000 --- a/website/translated_docs/pl/asyncio_index.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: "Asynchronous Programming" -sidebar_label: Introduction ---- - -On September 29, 2016 we released [Home Assistant 0.29](https://www.home-assistant.io/blog/2016/09/29/async-sleepiq-emoncms-stocks/) as part of our bi-weekly release schedule. This release introduced a complete overhaul of the core spearheaded by [Ben Bangert](https://github.com/bbangert/). - -The old core was set up like a “traditional” threaded application. Each resource that was not thread safe (ie. the state of entities) would be protected by a lock. This caused a lot of waiting and potential inconsistency because a task could now end up waiting halfway through its job until some resource got freed. - -Our new core is based on Python’s built-in **asyncio** module. Instead of having all threads have access to the core API objects, access is now limited to a special thread called the *event loop*. All components will now schedule themselves as a task to be executed by the event loop. This gives us the guarantee that only a single task is executed at the same time, meaning we no longer need any locks. - -The only problem with running everything inside the event loop is when a task does blocking I/O; something most third-party Python libraries do. For example, while requesting new information from a device, the core will stop running until we get a response from the device. To handle this, a task is able to suspend itself until the response is available, after which it will be enqueued in the event loop to process the result. - -For a task to be able to suspend itself, all code that it calls must support this capability. In practice, this would mean that each device integration will need a full rewrite of the library that offers the integration! As this is something that cannot be achieved, ever, a 100% backwards compatible API has been added so that no platform will require updating. - -The backwards compatible API schedules a task in a different thread and blocks that thread until the task has been processed by the event loop. \ No newline at end of file diff --git a/website/translated_docs/pl/asyncio_working_with_async.md b/website/translated_docs/pl/asyncio_working_with_async.md deleted file mode 100644 index 6f56876c..00000000 --- a/website/translated_docs/pl/asyncio_working_with_async.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: "Working with Async" ---- - -Although we have a backwards compatible API, using the async core directly will be a lot faster. Most core components have already been rewritten to leverage the async core. This includes the EntityComponent helper (foundation of light, switch, etc), scripts, groups and automation. - -## Interacting with the core - -[All methods in the Home Assistant core](https://dev-docs.home-assistant.io/en/master/api/core.html) are implemented in two flavors: an async version and a version to be called from other threads. The versions for other are merely wrappers that call the async version in a threadsafe manner. - -So if you are making calls to the core (the hass object) from within a callback or coroutine, use the methods that start with async_. If you need to call an async_ function that is a coroutine, your task must also be a coroutine. - -## Implementing an async component - -To make a component async, implement an async_setup. - -```python -def setup(hass, config): - # Setup your component outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup(hass, config): - # Setup your component inside of the event loop. -``` - -## Implementing an async platform - -For platforms we support async setup. Instead of setup_platform you need to have a coroutine async_setup_platform. - -```python -setup_platform(hass, config, add_entities, discovery_info=None): - # Setup your platform outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup_platform(hass, config, async_add_entities, - discovery_info=None): - # Setup your platform inside of the event loop -``` - -The only difference with the original parameters is that the `add_entities` function has been replaced by the async friendly callback `async_add_entities`. - -## Implementing an async entity - -You can make your entity async friendly by converting your update method to be async. This requires the dependency of your entities to also be async friendly! - -```python -class MyEntity(Entity): - def update(self): - """Retrieve latest state.""" - self._state = fetch_state() -``` - -Will turn into: - -```python -class MyEntity(Entity): - async def async_update(self): - """Retrieve latest state.""" - self._state = await async_fetch_state() -``` - -Make sure that all properties defined on your entity do not result in I/O being done. All data has to be fetched inside the update method and cached on the entity. This is because these properties are read from within the event loop and thus doing I/O will result in the core of Home Assistant waiting until your I/O is done. - -## Calling async functions from threads - -Sometimes it will happen that you’re in a thread and you want to call a function that is only available as async. Home Assistant includes a few async helper utilities to help with this. - -In the following example, `say_hello` will schedule `async_say_hello` and block till the function has run and get the result back. - -```python -import asyncio - -def say_hello(hass, target): - return asyncio.run_coroutine_threadsafe( - async_say_hello(hass, target), hass.loop).result() - -async def async_say_hello(hass, target): - return "Hello {}!".format(target) -``` - -## Calling sync functions from async - -If you are running inside an async context, it might sometimes be necessary to call a sync function. Do this like this: - -```python -# hub.update() is a sync function. -result = await hass.async_add_executor_job(hub.update) -``` - -## Starting independent task from async - -If you want to spawn a task that will not block the current async context, you can choose to create it as a task on the event loop. It will then be executed in parallel. - -```python -hass.async_create_task(async_say_hello(hass, target)) -``` \ No newline at end of file diff --git a/website/translated_docs/pl/auth_api.md b/website/translated_docs/pl/auth_api.md deleted file mode 100644 index 0fa664fa..00000000 --- a/website/translated_docs/pl/auth_api.md +++ /dev/null @@ -1,245 +0,0 @@ ---- -title: "Authentication API" -sidebar_label: API ---- - -This page will describe the steps required for your application to authorize against and integrate with Home Assistant instances. [See a demo](https://hass-auth-demo.glitch.me) powered by our helper lib [home-assistant-js-websocket](https://github.com/home-assistant/home-assistant-js-websocket). - -Each user has their own instance of Home Assistant which gives each user control over their own data. However, we also wanted to make it easy for third party developers to create applications that allow users to integrate with Home Assistant. To achieve this, we have adopted the [OAuth 2 specification](https://tools.ietf.org/html/rfc6749) combined with the [OAuth 2 IndieAuth extension](https://indieauth.spec.indieweb.org/) for generating clients. - -## Clients - -Before you can ask the user to authorize their instance with your application, you will need a client. In traditional OAuth2, the server needs to generate a client before a user can authorize. However, as each server belongs to a user, we've adopted a slightly different approach from [IndieAuth](https://indieauth.spec.indieweb.org/#client-identifier). - -The client ID you need to use is the website of your application. The redirect url has to be of the same host and port as the client ID. For example: - -- client id: `https://www.my-application.io` -- redirect uri: `https://www.my-application.io/hass/auth_callback` - -If you require a different redirect url (ie, if building a native app), you can add an HTML tag to the content of the website of your application (the client ID) with an approved redirect url. For example, add this to your site to whitelist redirect uri `hass://auth`: - -```html - -``` - -Home Assistant will scan the first 10kB of a website for link tags. - -## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) - -> All example URLs here are shown with extra spaces and new lines for display purposes only. - -The authorize url should contain `client_id` and `redirect_uri` as query parameters. - - http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2F%3Fauth_callback%3D1 - - -Optionally you can also include a `state` parameter, this will be added to the redirect uri. The state is perfect to store the instance url that you are authenticating with. Example: - - http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2Fauth_callback& - state=http%3A%2F%2Fhassio.local%3A8123 - - -The user will navigate to this link and be presented with instructions to log in and authorize your application. Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code and state as part of the query parameters. Example: - - https://hass-auth-demo.glitch.me/auth_callback - code=12345& - state=http%3A%2F%2Fhassio.local%3A8123 - - -This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section). - -## Token - -The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. In thee case of refresh token, the token endpoint is also capable of revoking a token. - -All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`. - -### Authorization code - -> All requests to the token endpoint need to contain the exact same client ID as was used to redirect the user to the authorize endpoint. - -Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is: - - grant_type=authorization_code& - code=12345& - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me - - -The return response will be an access and refresh token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "refresh_token": "IJKLMNOPQRST", - "token_type": "Bearer" -} -``` - -The access token is a short lived token that can be used to access the API. The refresh token can be used to fetch new access tokens. The `expires_in` value is seconds that the access token is valid. - -An HTTP status code of 400 will be returned if an invalid request has been issued. The HTTP status code will be 403 if a token is requested for an inactive user. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Refresh token - -Once you have retrieved a refresh token via the grant type `authorization_code`, you can use it to fetch new access tokens. The request body is: - - grant_type=refresh_token& - refresh_token=IJKLMNOPQRST& - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me - - -The return response will be an access token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "token_type": "Bearer" -} -``` - -An HTTP status code of 400 will be returned if an invalid request has been issued. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Revoking a refresh token - -> client_id is not need for revoke refresh token - -The token endpoint is also capable of revoking a refresh token. Revoking a refresh token will immediately revoke the refresh token and all access tokens that it has ever granted. To revoke a refresh token, make the following request: - - token=IJKLMNOPQRST& - action=revoke - - -The request will always respond with an empty body and HTTP status 200, regardless if the request was successful. - -## Long-lived access token - -A long-lived access token is usually used for 3rd party API calls and webhook-ish integrations. To generate a long-lived access token, an active websocket connection has to be established. - -Send websocket command `auth/long_lived_access_token` will create a long-lived access token for current user. Access token will not be saved in Home Assistant. User need to record the token in secure place. - -```json -{ - "id": 11, - "type": "auth/long_lived_access_token", - "client_name": "GPS Logger", - "client_icon": null, - "lifespan": 365 -} -``` - -Result will be a long-lived access token: - -```json -{ - "id": 11, - "type": "result", - "success": true, - "result": "ABCDEFGH" -} -``` - -Additionally, a long-lived access token can be created using the UI tool located at the bottom of the user's Home Assistant profile page. - -## Making authenticated requests - -Once you have an access token, you can make authenticated requests to the Home Assistant APIs. - -For the websocket connection, pass the access token in the [authentication message](https://developers.home-assistant.io/docs/en/external_api_websocket.html#authentication-phase). - -For HTTP requests, pass the token type and access token as the authorization header: - - Authorization: Bearer ABCDEFGH - - -### Example: cURL - -```shell -curl -X GET \ - https://your.awesome.home/api/error/all \ - -H 'Authorization: Bearer ABCDEFGH' -``` - -### Example: Python - -```python -import requests - -url = "https://your.awesome.home/api/error/all" -headers = { - 'Authorization': "Bearer ABCDEFGH", -} -response = requests.request('GET', url, headers=headers) - -print(response.text) -``` - -### Example: NodeJS - -```JavaScript -fetch('https://your.awesome.home/api/error/all', { - headers: { Authorization: 'Bearer ABCDEFGH' } -}).then(function (response) { - if (!response.ok) { - return Promise.reject(response); - } - return response.text(); -}).then(function (body ) { - console.log(body); -}); -``` - -If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and so the user is no longer logged in. You should clear the user's data and ask the user to authorize again. - -## Signed paths - -Sometimes you want a user to make a GET request to Home Assistant to download data. In this case the normal auth system won't do, as we can't link the user to an API with the auth header attached to it. In that case, a signed path can help. - -A signed path is a normal path on our server, like `/api/states`, but with an attached secure authentication signature. The user is able to navigate to this path and will be authorised as the access token that created the signed path. Signed paths can be created via the websocket connection and are meant to be shortlived. The default expiration is 30 seconds. - -To get a signed path, send the following command: - -```js -{ - "type": "auth/sign_path", - "path": "/api/states", - // optional, expiration time in seconds. Defaults to 30 seconds - "expires": 20 -} -``` - -The response will contain the signed path: - -```js -{ - "path": "/api/states?authSig=ABCDEFGH" -} -``` - -Some things to note about a signed path: - -- If the refresh token is deleted, the signed url is no longer valid. -- If the user is deleted, the signed url is no longer valid (because the refresh token will be deleted). -- If Home Assistant is restarted, the signed url is no longer valid. -- Access is only validated when the request is received. If a response takes longer than the expiration time (ie, downloading a large file), the download will continue after the expiration date has passed. \ No newline at end of file diff --git a/website/translated_docs/pl/auth_auth_module.md b/website/translated_docs/pl/auth_auth_module.md deleted file mode 100644 index e0e000a7..00000000 --- a/website/translated_docs/pl/auth_auth_module.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: "Multi-factor Authentication Modules" ---- - -Multi-factor Authentication Modules are used in conjunction with [Authentication Provider](auth_auth_provider.html) to provide a fully configurable authentication framework. Each MFA module may provide one multi-factor authentication function. User can enable multiple mfa modules, but can only select one module in login process. - -## Defining an mfa auth module - -> We currently only support built-in mfa auth modules. Support for custom auth modules might arrive in the future. - -Multi-factor Auth modules are defined in `homeassistant/auth/mfa_modules/.py`. The auth module will need to provide an implementation of the `MultiFactorAuthModule` class. - -For an example of a fully implemented auth module, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/mfa_modules/insecure_example.py). - -Multi-factor Auth modules shall extend the following methods of `MultiFactorAuthModule` class. - -| method | Required | Description | -| ---------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- | -| `@property def input_schema(self)` | Yes | Return a schema defined the user input form. | -| `async def async_setup_flow(self, user_id)` | Yes | Return a SetupFlow to handle the setup workflow. | -| `async def async_setup_user(self, user_id, setup_data)` | Yes | Set up user for use this auth module. | -| `async def async_depose_user(self, user_id)` | Yes | Remove user information from this auth module. | -| `async def async_is_user_setup(self, user_id)` | Yes | Return whether user is set up. | -| `async def async_validate(self, user_id, user_input)` | Yes | Given a user_id and user input, return validation result. | -| `async def async_initialize_login_mfa_step(self, user_id)` | No | Will be called once before display the mfa step of login flow. This is not initialization for the MFA module but the mfa step in login flow. | - -## Setup Flow - -Before user can use a multi-factor auth module, it has to be enabled or set up. All available modules will be listed in user profile page, user can enable the module he/she wants to use. A setup data entry flow will guide user finish the necessary steps. - -Each MFA module need to implement a setup flow handler extends from `mfa_modules.SetupFlow` (if only one simple setup step need, `SetupFlow` can be used as well). For example for Google Authenticator (TOTP, Time-based One Time Password) module, the flow will need to be: - -- Generate a secret and store it on instance of setup flow -- Return `async_show_form` with a QR code in the description (injected as base64 via `description_placeholders`) -- User scans code and enters a code to verify it scanned correctly and clock in synced -- TOTP module saved the secret along with user_id, module is enabled for user - -## Workflow - -![Multi Factor Authentication Workflow](/img/en/auth/mfa_workflow.png) - - - -## Configuration example - -```yaml -# configuration.xml -homeassistant: - auth_providers: - - type: homeassistant - - type: legacy_api_password - auth_mfa_modules: - - type: totp - - type: insecure_example - users: [{'user_id': 'a_32_bytes_length_user_id', 'pin': '123456'}] -``` - -In this example, user will first select from `homeassistant` or `legacy_api_password` auth provider. For `homeassistant` auth provider, user will first input username/password, if that user enabled both `totp` and `insecure_example`, then user need select one auth module, then input Google Authenticator code or input pin code base on the selection. - -> insecure_example is only for demo purpose, please do not use it in production. - -## Validation session - -Not like auth provider, auth module use session to manage the validation. After auth provider validated, mfa module will create a validation session, include an experiation time and user_id from auth provider validate result. Mutli-factor auth module will not only verify the user input, but also verify the session is not expired. The validation session data is stored in your configuration directory. \ No newline at end of file diff --git a/website/translated_docs/pl/auth_auth_provider.md b/website/translated_docs/pl/auth_auth_provider.md deleted file mode 100644 index b652973d..00000000 --- a/website/translated_docs/pl/auth_auth_provider.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: "Authentication Providers" ---- - -Authentication providers confirm the identity of users. The user proofs their identity by going through the login flow for an auth provider. The auth provider defines the login flow and can ask the user all information this needs. This will commonly be username and password but could also include a 2FA token or other challenges. - -Once an authentication provider has confirmed the identity of a user, it will pass that on to Home Assistant in the form of a Credentials object. - -## Defining an auth provider - -> We currently only support built-in auth providers. Support for custom auth providers might arrive in the future. - -Auth providers are defined in `homeassistant/auth/providers/.py`. The auth provider module will need to provide an implementation of the `AuthProvider` class and `LoginFlow` class, it is what asks user for information and validates it base on `data_entry_flow`. - -For an example of a fully implemented auth provider, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/providers/insecure_example.py). - -Auth providers shall extend the following methods of `AuthProvider` class. - -| method | Required | Description | -| ---------------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------- | -| async def async_login_flow(self) | Yes | Return an instance of the login flow for a user to identify itself. | -| async def async_get_or_create_credentials(self, flow_result) | Yes | Given the result of a login flow, return a credentials object. This can either be an existing one or a new one. | -| async def async_user_meta_for_credentials(credentials) | No | Callback called Home Assistant is going to create a user from a Credentials object. Can be used to populate extra fields for the user. | - -Auth providers shall extend the following methods of `LoginFlow` class. - -| method | Required | Description | -| -------------------------------------------------- | -------- | ------------------------------------------------ | -| async def async_step_init(self, user_input=None) | Yes | Handle the login form, see more detail in below. | - -## async_step_init of LoginFlow - -> We may change this inteface in near future. - -`LoginFlow` extends `data_entry_flow.FlowHandler`. The first step of data entry flow is hard coded as `init`, so each flow has to implement `async_step_init` method. The pattern of `async_step_init` likes following pseudo-code: - -```python -async def async_step_init(self, user_input=None): - return self.async_show_form(step_id='init', data_schema='some schema to construct ui form') if user_input is None - return self.async_show_form(step_id='init', errors) if user_input is invalid - return await self.async_finish(username) if user_input is valid -``` \ No newline at end of file diff --git a/website/translated_docs/pl/auth_index.md b/website/translated_docs/pl/auth_index.md deleted file mode 100644 index 695e6c7d..00000000 --- a/website/translated_docs/pl/auth_index.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: "Authentication" -sidebar_label: Introduction ---- - -Home Assistant has a built-in authentication system allowing different users to interact with Home Assistant. The authentication system consist of various parts. - -![Overview of how the different parts interact](/img/en/auth/architecture.png) - -## Authentication providers - -An authentication provider is used for users to authenticate themselves. It's up to the authentication provider to choose the method of authentication and the backend to use. By default we enable the built-in Home Assistant authentication provider which stores the users securely inside your configuration directory. - -The authentication providers that Home Assistant will use are specified inside `configuration.yaml`. It is possible to have multiple instances of the same authentication provider active. In that case, each will be identified by a unique identifier. Authentication providers of the same type will not share credentials. - -## Credentials - -Credentials store the authentication of a user with a specific authentication provider. It is produced when a user successfully authenticates. It will allow the system to find the user in our system. If the user does not exist, a new user will be created. This user will not be activated but will require approval by the owner. - -It is possible for a user to have multiple credentials linked to it. However, it can only have a single credential per specific authentication provider. - -## Users - -Each person is a user in the system. To log in as a specific user, authenticate with any of the authentication providers that are linked to this user. When a user logs in, it will get a refresh and an access token to make requests to Home Assistant. - -### Owner - -The user that is created during onboarding will be marked as "owner". The owner is able to manage other users and will always have access to all permissions. - -## Groups - -Users are a member of one or more groups. Group membership is how a user is granted permissions. - -## Permission Policy - -This is the permission policy that describes to which resources a group has access. For more information about permissions and policies, see [Permissions](auth_permissions.md). - -## Access and refresh tokens - -Applications that want to access Home Assistant will ask the user to start an authorization flow. The flow results in an authorization code when a user successfully authorizes the application with Home Assistant. This code can be used to retrieve an access and a refresh token. The access token will have a limited lifetime while refresh tokens will remain valid until a user deletes it. - -The access token is used to access the Home Assistant APIs. The refresh token is used to retrieve a new valid access token. - -### Refresh token types - -There are three different types of refresh tokens: - -- *Normal*: These are the tokens that are generated when a user authorizes an application. The application will hold on to these tokens on behalf of the user. -- *Long-lived Access Token*: These are refresh tokens that back a long lived access token. They are created internally and never exposed to the user. -- *System*: These tokens are limited to be generated and used by system users like Hass.io. They are never exposed to the user. \ No newline at end of file diff --git a/website/translated_docs/pl/auth_permissions.md b/website/translated_docs/pl/auth_permissions.md deleted file mode 100644 index 9aed470e..00000000 --- a/website/translated_docs/pl/auth_permissions.md +++ /dev/null @@ -1,266 +0,0 @@ ---- -title: "Permissions" ---- - -> This is an experimental feature that is not enabled or enforced yet - -Permissions limit the things a user has access to or can control. Permissions are attached to groups, of which a user can be a member. The combined permissions of all groups a user is a member of decides what a user can and cannot see or control. - -Permissions do not apply to the user that is flagged as "owner". This user will always have access to everything. - -## General permission structure - -Policies are dictionaries that at the root level consist of different categories of permissions. In the current implementation this is limited to just entities. - -```python -{ - "entities": … -} -``` - -Each category can further split into subcategories that describe parts of that category. - -```python -{ - "entities": { - "domains": …, - "entity_ids": … - } -} -``` - -If a category is omitted, the user will not have permission to that category. - -When defining a policy, any dictionary value at any place can be replaced with `True` or `None`. `True` means that permission is granted and `None` means use default, which is deny access. - -## Entities - -Entity permissions can be set on a per entity and per domain basis using the subcategories `entity_ids`, `device_ids`, `area_ids` and `domains`. You can either grant all access by setting the value to `True`, or you can specify each entity individually using the "read", "control", "edit" permissions. - -The system will return the first matching result, based on the order: `entity_ids`, `device_ids`, `area_ids`, `domains`, `all`. - -```json -{ - "entities": { - "domains": { - "switch": true - }, - "entity_ids": { - "light.kitchen": { - "read": true, - "control": true - } - } - } -} -``` - -## Merging policies - -If a user is a member of multiple groups, the groups permission policies will be combined into a single policy at runtime. When merging policies, we will look at each level of the dictionary and compare the values for each source using the following methodology: - -1. If any of the values is `True`, the merged value becomes `True`. -2. If any value is a dictionary, the merged value becomes a dictionary created by recursively checking each value using this methodology. -3. If all values are `None`, the merged value becomes `None`. - -Let's look at an example: - -```python -{ - "entities": { - "entity_ids": { - "light.kitchen": True - } - } -} -``` - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -Once merged becomes - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -## Checking permissions - -We currently have two different permission checks: can the user do the read/control/edit operation on an entity, and is the user an admin and thus allowed to change this configuration setting. - -Certain APIs will always be accessible to all users, but might offer a limited scope based on the permissions, like rendering a template. - -### Checking permissions - -To check a permission, you will need to have access to the user object. Once you have the user object, checking the permission is easy. - -```python -from homeassistant.exceptions import Unauthorized -from homeasistant.permissions.const import ( - POLICY_READ, POLICY_CONTROL, POLICY_EDIT -) - -# Raise error if user is not an admin -if not user.is_admin: - raise Unauthorized() - - -# Raise error if user does not have access to control an entity -# Available policies: POLICY_READ, POLICY_CONTROL, POLICY_EDIT -if not user.permissions.check_entity(entity_id, POLICY_CONTROL): - raise Unauthorized() -``` - -### The context object - -All service calls, fired events and states in Home Assistant have a context object. This object allows us to attribute changes to events and services. These context objects also contain a user id, which is used for checking the permissions. - -It's crucial for permission checking that actions taken on behalf of the user are done with a context containing the user ID. If you are in a service handler, you should re-use the incoming context `call.context`. If you are inside a WebSocket API or Rest API endpoint, you should create a context with the correct user: - -```python -from homeassistant.core import Context - -await hass.services.async_call('homeassistant', 'stop', context=Context( - user_id=user.id -), blocking=True) -``` - -### If a permission check fails - -When you detect an anauthorized action, you should raise the `homeassistant.exceptions.Unauthorized` exception. This exception will cancel the current action and notifies the user that their action is unauthorized. - -The `Unauthorized` exception has various parameters, to identify the permission check that failed. All fields are optional. - -| # Not all actions have an ID (like adding config entry) | # We then use this fallback to know what category was unauth - -| Parameter | Description | -| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| context | The context of the current call. | -| user_id | The user ID that we tried to operate on. | -| entity_id | The entity ID that we tried to operate on. | -| config_entry_id | The config entry ID that we tried to operate on. | -| perm_category | The permission category that we tested. Only necessary if we don't have an object ID that the user tried to operate on (like when we create a config entry). | -| permission | The permission that we tested, ie `POLICY_READ`. | - -### Securing a service call handler - -Service calls allow a user to control entities or with the integration as a whole. A service call uses the attached context to see which user invoked the command. Because context is used, it is important that you also pass the call context to all service calls. - -All services that are registered via the entity component (`component.async_register_entity_service()`) will automatically have their permissions checked. - -#### Checking entity permissions - -Your service call handler will need to check the permissions for each entity that it will act on. - -```python -from homeassistant.exceptions import Unauthorized, UnknownUser -from homeassistant.auth.permissions.const import POLICY_CONTROL - -async def handle_entity_service(call): - """Handle a service call.""" - entity_ids = call.data['entity_id'] - - for entity_id in entity_ids: - if call.context.user_id: - user = await hass.auth.async_get_user(call.context.user_id) - - if user is None: - raise UnknownUser( - context=call.context, - entity_id=entity_id, - permission=POLICY_CONTROL, - ) - - if not user.permissions.check_entity(entity_id, POLICY_CONTROL): - raise Unauthorized( - context=call.context, - entity_id=entity_id, - permission=POLICY_CONTROL, - ) - - # Do action on entity - - -async def async_setup(hass, config): - hass.services.async_register(DOMAIN, 'my_service', handle_entity_service) - return True -``` - -#### Checking admin permission - -Starting Home Assistant 0.90, there is a special decorator to help protect services that require admin access. - -```python -# New in Home Assistant 0.90 -async def handle_admin_service(call): - """Handle a service call.""" - # Do admin action - - -async def async_setup(hass, config): - hass.helpers.service.async_register_admin_service( - DOMAIN, 'my_service', handle_admin_service, vol.Schema({}) - ) - return True -``` - -### Securing a REST API endpoint - -```python -from homeassistant.core import Context -from homeassistant.components.http.view import HomeAssistantView -from homeassistant.exceptions import Unauthorized - - -class MyView(HomeAssistantView): - """View to handle Status requests.""" - - url = '/api/my-component/my-api' - name = 'api:my-component:my-api' - - async def post(self, request): - """Notify that the API is running.""" - hass = request.app['hass'] - user = request['hass_user'] - - if not user.is_admin: - raise Unauthorized() - - hass.bus.async_fire('my-component-api-running', context=Context( - user_id=user.id - )) - - return self.json_message("Done.") -``` - -### Securing a Websocket API endpoint - -Verifying permissions in a Websocket API endpoint can be done by accessing the user via `connection.user`. If you need to check admin access, you can use the built-in `@require_admin` decorator. - -```python -from homeassistant.compnents import websocket_api - - -async def async_setup(hass, config): - hass.components.websocket_api.async_register_command(websocket_create) - return True - - -@websocket_api.require_admin -@websocket_api.async_response -@websocket_api.websocket_command({ - vol.Required('type'): 'my-component/my-action', -}) -async def websocket_create(hass, connection, msg): - """Create a user.""" - # Do action -``` \ No newline at end of file diff --git a/website/translated_docs/pl/config_entries_config_flow_handler.md b/website/translated_docs/pl/config_entries_config_flow_handler.md deleted file mode 100644 index 6fe750d0..00000000 --- a/website/translated_docs/pl/config_entries_config_flow_handler.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Integration Configuration -sidebar_label: Configuration ---- - -> This option is currently only available for built-in components. - -Integrations can be set up via the user interface by adding support for config entries. Config entries uses the [data flow entry framework](data_entry_flow_index.md) to allow users to create entries. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like Hass.io). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -To register your config flow handler with Home Assistant, register it with the config entries `HANDLERS` registry: - -```python -from homeassistant import config_entries - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(config_entries.ConfigFlow): -``` - -All config flow handlers will also need to add their domain name to the `FLOWS` constant in `homeassistant/config_entries.py`. - -## Discovering your config flow - -Home Assistant has a discovery integration that scans the network for available devices and services and will trigger the config flow of the appropriate integration. Discovery is limited to UPnP and zeroconf/mDNS. - -To have your integration be discovered, you will have to extend the [NetDisco library](https://github.com/home-assistant/netdisco) to be able to find your device. This is done by adding a new discoverable. [See the repository for examples of existing discoverable.](https://github.com/home-assistant/netdisco/tree/master/netdisco/discoverables) - -Once done, you will have to update the discovery integration to make it aware which discovery maps to which integration, by updating [this list](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery/__init__.py#L55). - -Finally, you will have to add support to your config flow to be triggered from discovery. This is done by adding a new discovery step. Make sure that your discovery step does not automatically create an entry. All discovered config flows are required to have a confirmation from the user. - -Once discovered, the user will be notified that they can continue the flow from the config panel. - -```python -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` - -When the translations are merged into Home Assistant, they will be automatically uploaded to [Lokalise](https://lokalise.co/) where the translation team will help to translate them in other languages. [More info on translating Home Assistant.](internationalization_translation.md) - -## Triggering other config flows - -If you are writing an integration that discovers other integrations, you will want to trigger their config flows so the user can set them up. Do this by passing a source parameter and optional user input when initializing the config entry: - -```python -await hass.config_entries.flow.async_init( - 'hue', data=discovery_info, - context={'source': config_entries.SOURCE_DISCOVERY}) -``` \ No newline at end of file diff --git a/website/translated_docs/pl/config_entries_index.md b/website/translated_docs/pl/config_entries_index.md deleted file mode 100644 index 2416509c..00000000 --- a/website/translated_docs/pl/config_entries_index.md +++ /dev/null @@ -1,166 +0,0 @@ ---- -title: Config Entries -sidebar_label: Introduction ---- - -Config Entries are configuration data that are persistently stored by Home Assistant. A config entry is created by a user via the UI. The UI flow is powered by a [config flow handler](config_entries_config_flow_handler.md) as defined by the component. Config entries can also have an extra [options flow handler](config_entries_options_flow_handler.md), also defined by the component. - -## Lifecycle - -| State | Description | -| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| not loaded | The config entry has not been loaded. This is the initial state when a config entry is created or when Home Assistant is restarted. | -| loaded | The config entry has been loaded. | -| setup error | An error occurred when trying to set up the config entry. | -| setup retry | A dependency of the config entry was not ready yet. Home Assistant will automatically retry loading this config entry in the future. Time between attempts will automatically increase. | -| migration error | The config entry had to be migrated to a newer version, but the migration failed. | -| failed unload | The config entry was attempted to be unloaded, but this was either not supported or it raised an exception. | -G - - - - - not loaded - - -not loaded - - - loaded - - -loaded - - - not loaded->loaded - - - - - - - setup error - - -setup error - - - not loaded->setup error - - - - - - - setup retry - - -setup retry - - - not loaded->setup retry - - - - - - - migration error - - -migration error - - - not loaded->migration error - - - - - - - loaded->not loaded - - - - - - - failed unload - - -failed unload - - - loaded->failed unload - - - - - - - setup error->not loaded - - - - - - - setup retry->not loaded - - - - - - - -## Setting up an entry - -During startup, Home Assistant first calls the [normal component setup](https://developers.home-assistant.io/docs/en/creating_component_index.html), and then call the method `async_setup_entry(hass, entry)` for each entry. If a new Config Entry is created at runtime, Home Assistant will also call `async_setup_entry(hass, entry)` ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L119)). - -#### For platforms - -If a component includes platforms, it will need to forward the Config Entry to the platform. This can be done by calling the forward function on the config entry manager ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/bridge.py#L81)): - -```python -# Use `hass.async_add_job` to avoid a circular dependency between the platform and the component -hass.async_add_job(hass.config_entries.async_forward_entry_setup(config_entry, 'light')) -``` - -For a platform to support config entries, it will need to add a setup entry method ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/light/hue.py#L60)): - -```python -async def async_setup_entry(hass, config_entry, async_add_devices): -``` - -## Unloading entries - -Components can optionally support unloading a config entry. When unloading an entry, the component needs to clean up all entities, unsubscribe any event listener and close all connections. To implement this, add `async_unload_entry(hass, entry)` to your component ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L136)). - -For each platform that you forwarded the config entry to, you will need to forward the unloading too. - -```python -await self.hass.config_entries.async_forward_entry_unload(self.config_entry, 'light') -``` - -If you need to clean up resources used by an entity in a platform, have the entity implement the [`async_will_remove_from_hass`](entity_index.md#async_will_remove_from_hass) method. - -## Removal of entries - -If a component needs to clean up code when an entry is removed, it can define a removal method: - -```python -async def async_remove_entry(hass, entry) -> None: - """Handle removal of an entry.""" -``` \ No newline at end of file diff --git a/website/translated_docs/pl/config_entries_options_flow_handler.md b/website/translated_docs/pl/config_entries_options_flow_handler.md deleted file mode 100644 index 03be7419..00000000 --- a/website/translated_docs/pl/config_entries_options_flow_handler.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Integration Configuration Options -sidebar_label: Configuration Options ---- - -> This option is currently only available for built-in components. - -An integration that is configured via a config entry can expose options to the user to allow tweaking behavior of the integration, like which devices or locations should be integrated. - -Config Entry Options uses the [Data Flow Entry framework](data_entry_flow_index.md) to allow users to update a config entries options. Components that want to support config entry options will need to define a Options Flow Handler. - -## Options support - -For an integration to support options it needs to have an `async_get_options_flow` method in its config flow handler. Calling it will return an instance of the components options flow handler. - -```python -@staticmethod -@callback -def async_get_options_flow(config, options): - return OptionsFlowHandler(config, options) -``` - -## Flow handler - -The Flow handler works just like the config flow handler, except that the first step in the flow will always be `async_step_init`. - -```python -class OptionsFlowHandler(data_entry_flow.FlowHandler): - def __init__(self, config, options): -``` - -## Signal updates - -If the component should act on updated options, you can register an update listener to the config entry that will be called when the entry is updated. - -```python -entry.add_update_listener(update_listener) -``` - -The Listener shall be an async function that takes the same input as async_setup_entry. Options can then be accessed from `entry.options`. - -```python -async def update_listener(hass, entry): -``` \ No newline at end of file diff --git a/website/translated_docs/pl/configuration_yaml_index.md b/website/translated_docs/pl/configuration_yaml_index.md deleted file mode 100644 index 15f42083..00000000 --- a/website/translated_docs/pl/configuration_yaml_index.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: "Integration Configuration via YAML" -sidebar_label: Configuration via YAML ---- - -`configuration.yaml` is a configuration file defined by the user. It is automatically created by Home Assistant on first launch. It defines which components to load. - -## Pre-processing - -Home Assistant will do some pre-processing on the config based on the components that are specified to load. - -### CONFIG_SCHEMA - -If a component defines a variable `CONFIG_SCHEMA`, the config object that is passed in will be the result of running the config through `CONFIG_SCHEMA`. `CONFIG_SCHEMA` should be a voluptuous schema. - -### PLATFORM_SCHEMA - -If a component defines a variable `PLATFORM_SCHEMA`, the component will be treated as an entity component. The configuration of entity components is a list of platform configurations. - -Home Assistant will gather all platform configurations for this component. It will do so by looking for configuration entries under the domain of the component (ie `light`) but also under any entry of domain + extra text. - -While gathering the platform configs, Home Assistant will validate them. It will see if the platform exists and if the platform defines a PLATFORM_SCHEMA, validate against that schema. If not defined, it will validate the config against the PLATFORM_SCHEMA defined in the component. Any configuration that references non existing platforms or contains invalid config will be removed. - -The following `configuration.yaml`: - -```yaml -unrelated_component: - some_key: some_value - -switch: - platform: example1 - -switch living room: - - - platform: example2 - some_config: true - - platform: invalid_platform -``` - -will be passed to the component as - -```python -{ - "unrelated_component": { - "some_key": "some_value" - }, - "switch": [ - { - "platform": "example1" - }, - { - "platform": "example2, - "some_config": True - } - ] -} -``` \ No newline at end of file diff --git a/website/translated_docs/pl/creating_component_code_review.md b/website/translated_docs/pl/creating_component_code_review.md deleted file mode 100644 index 2a87cc44..00000000 --- a/website/translated_docs/pl/creating_component_code_review.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: "Checklist for creating a component" -sidebar_label: Component Checklist ---- - -A checklist of things to do when you're adding a new component. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - -1. Follow our [Style guidelines](development_guidelines.md) -2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - - Only add new constants to `const.py` if they are widely used. Otherwise keep them on components level - -### 1. Requirements - -1. Requirements have been added to [`manifest.json`](creating_integration_manifest.md). The `REQUIREMENTS` constant is deprecated. -2. Requirement version should be pinned: `"requirements": ['phue==0.8.1']` -3. We no longer want requirements hosted on GitHub. Please upload to PyPi. -4. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Configuration - -1. Voluptuous schema present for [configuration validation](development_validation.md) -2. Default parameters specified in voluptuous schema, not in `setup(…)` -3. Schema using as many generic config keys as possible from `homeassistant.const` -4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`. -5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation` -6. Never depend on users adding things to `customize` to configure behavior inside your component. - -### 3. Component/platform communication - -1. You can share data with your platforms by leveraging `hass.data[DOMAIN]`. -2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`. - -### 4. Communication with devices/services - -1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - - ```python - # bad - status = requests.get(url('/status')) - - # good - from phue import Bridge - bridge = Bridge(...) - status = bridge.status() - ``` - - [Tutorial on publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) - -### 5. Make your pull request as small as possible - -Keep a new integration to the minimum functionality needed for someone to get value out of the integration. This allows reviewers to sign off on smaller chunks of code one at a time, and lets us get your new integration/features in sooner. **Pull requests containing large code dumps will not be a priority for review and may be closed.** - -- Limit to a single platform -- Do not add features not needed to directly support the single platform (such as custom services) -- Do not mix clean-ups and new features in a single pull request. -- Do not solve several issues in a single pull request. -- Do not submit pull requests that depend on other work which is still unmerged. - -### 6. Event names - -Prefix component event names with the domain name. For example, use `netatmo_person` instead of `person` for the `netatmo` component. - -### 7. Tests - -Strongly consider adding tests for your component to minimize future regressions. \ No newline at end of file diff --git a/website/translated_docs/pl/creating_component_deps_and_reqs.md b/website/translated_docs/pl/creating_component_deps_and_reqs.md deleted file mode 100644 index c7826476..00000000 --- a/website/translated_docs/pl/creating_component_deps_and_reqs.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: "" ---- - -[This page has moved.](creating_integration_manifest.md) - - diff --git a/website/translated_docs/pl/creating_component_generic_discovery.md b/website/translated_docs/pl/creating_component_generic_discovery.md deleted file mode 100644 index cf5fc3a1..00000000 --- a/website/translated_docs/pl/creating_component_generic_discovery.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -title: "Integration with Multiple Platforms" -sidebar_label: Multiple platforms ---- - -Most integrations consist of a single platform. And in that case, it's fine to just define that one platform. However, if you are going to add a second platform, you will want to centralize your connection logic. This is done inside the component (`__init__.py`). - -If your integration is configurable via `configuration.yaml`, it will cause the entry point of your configuration to change, as now users will need to set up your integration directly, and it is up to your integration to set up the platforms. - -## Loading platforms when configured via a config entry - -If your integration is set up via a config entry, you will need to forward the config entry to the appropriate integration to set up your platform. For more info, see the [config entry documentation](config_entries_index.md#for-platforms). - -## Loading platforms when configured via configuration.yaml - -If your integration is not using config entries, it will have to use our discovery helpers to set up its platforms. Note, this approach does not support unloading. - -To do this, you will need to use the `load_platform` and `async_load_platform` methods from the discovery helper. - -- See also a [full example that implementing this logic](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_load_platform/) \ No newline at end of file diff --git a/website/translated_docs/pl/creating_component_index.md b/website/translated_docs/pl/creating_component_index.md deleted file mode 100644 index 9f02858f..00000000 --- a/website/translated_docs/pl/creating_component_index.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: "Creating a Minimal Component" -sidebar_label: "Minimal Component" ---- - -Alright, you learned about the [manifest](creating_integration_manifest.md), so it's time to write your first code for your integration. AWESOME. Don't worry, we've tried hard to keep it as easy as possible. - -More extensive examples of integrations are available from [our example repository](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/). - -## The code - -Each component needs to have 2 basic parts: it needs to define a `DOMAIN` constant that contains the domain of the integration. The second part is that it needs to define a setup method that returns a boolean if the set up was successful. So let's take a look at how this looks: - -```python -DOMAIN = 'hello_state' - -def setup(hass, config): - hass.states.set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -And if you prefer an async component: - -```python -DOMAIN = 'hello_state' - -async def async_setup(hass, config): - hass.states.async_set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -That's it! If you load this, you will see a new state in the state machine. - -To load this, add `hello_state:` to your `configuration.yaml` file and create a file `/custom_components/hello_state/__init__.py` with one of the two codeblocks above to test it locally. \ No newline at end of file diff --git a/website/translated_docs/pl/creating_integration_file_structure.md b/website/translated_docs/pl/creating_integration_file_structure.md deleted file mode 100644 index 3a535d07..00000000 --- a/website/translated_docs/pl/creating_integration_file_structure.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: "Integration File Structure" -sidebar_label: "File Structure" ---- - -Each integration is stored inside a directory named after the integration domain. The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. So all files for this integration are in the folder `mobile_app/`. - -The bare minimum content of this folder looks like this: - -- `manifest.json`: The manifest file describes the integration and its dependencies. [More info](creating_integration_manifest.md) -- `__init__.py`: The component file. If the integration only offers a platform, you can keep this file limited to a docstring introducing the integration `"""The Mobile App integration."""`. - -## Integrating devices - `light.py`, `switch.py` etc - -If your integration is going to integrate one or more devices, you will need to do this by creating a platform that interacts with an entity integration. For example, if you want to represent a light device inside Home Assistant, you will create `light.py`, which will contain a light platform for the light integration. - -- More info on [available entity integrations](entity_index.md). -- More info on [creating platforms](creating_platform_index.md). - -## Integrating services - `services.yaml` - -If your integration is going to register services, it will need to provide a description of the available services. The description is stored in `services.yaml`. [More information about `services.yaml`.](dev_101_services.md) - -## Where Home Assistant looks for integrations - -Home Assistant will look for an integration when it sees the domain referenced in the config file (i.e. `mobile_app:`) or if it is a dependency of another integration. Home Assistant will look at the following locations: - -- `/custom_components/` -- `homeassistant/components/` (built-in integrations) - -You can override a built-in integration by having an integration with the same domain in your `config/custom_components` folder. Note that overriding built-in components is not recommended as you will no longer get updates. It is recommended to pick a unique name. \ No newline at end of file diff --git a/website/translated_docs/pl/creating_integration_manifest.md b/website/translated_docs/pl/creating_integration_manifest.md deleted file mode 100644 index 7c76a6d7..00000000 --- a/website/translated_docs/pl/creating_integration_manifest.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: "Integration Manifest" -sidebar_label: "Manifest" ---- - -Since 0.92.0, every integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, except for custom components. - -```json -{ - "domain": "hue", - "name": "Philips Hue", - "documentation": "https://www.home-assistant.io/components/hue", - "dependencies": ["mqtt"], - "codeowners": ["@balloob"], - "requirements": ["aiohue==1.9.1"] -} -``` - -Or a minimal example that you can copy into your project: - -```json -{ - "domain": "your_domain_name", - "name": "Your Integration", - "documentation": "https://www.example.com", - "dependencies": [], - "codeowners": [], - "requirements": [] -} -``` - -## Domain - -The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. - -## Name - -The name of the integration. - -## Documentation - -The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/` - -## Dependencies - -Dependencies are other Home Assistant integrations that you want Home Assistant to set up successfully prior to the integration being loaded. This can be necessary in case you want to offer functionality from that other integration, like using webhooks or an MQTT connection. - -## Code Owners - -GitHub usernames or team names of people that are responsible for this integration. You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included. - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you running in a virtual environment. This will make sure that all requirements are present at startup. If steps fail, like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is an array of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v3.2.0: `["pychromecast==3.2.0"]`. - -> Because of how Home Assistant installs requirements on demand, actual Python imports of your requirements should be done inside functions instead of at the root level of your Python files. - -### Custom requirements during development & testing - -During the development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using `pychromecast` as an example: - -```bash -pip install pychromecast==3.2.0 --target ~/.homeassistant/deps -hass --skip-pip -``` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is specified in `requirements`. - -If you need to make changes to a requirement to support your component, it's also possible to install a development version of the requirement using `pip install -e`: - -```bash -git clone https://github.com/balloob/pychromecast.git -pip install -e ./pychromecast -hass --skip-pip -``` \ No newline at end of file diff --git a/website/translated_docs/pl/creating_platform_code_review.md b/website/translated_docs/pl/creating_platform_code_review.md deleted file mode 100644 index a7609f74..00000000 --- a/website/translated_docs/pl/creating_platform_code_review.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: "Checklist for creating a platform" -sidebar_label: Platform Checklist ---- - -A checklist of things to do when you're adding a new platform. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - -1. Follow our [Style guidelines](development_guidelines.md) -2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - - Only add new constants to `const.py` if they are widely used. Otherwise keep them on platform level - - Use `CONF_MONITORED_CONDITIONS` instead of `CONF_MONITORED_VARIABLES` - -### 1. Requirements - -1. Requirements have been added to [`manifest.json`](creating_integration_manifest.md). The `REQUIREMENTS` constant is deprecated. -2. Requirement version should be pinned: `"requirements": ['phue==0.8.1']` -3. We no longer want requirements hosted on GitHub. Please upload to PyPi. -4. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Dependencies - -1. If you depend on a component for the connection, add it to your dependencies in [`manifest.json`](creating_integration_manifest.md): `"dependencies": ['nest']`. The `DEPENDENCIES` constant is deprecated. - -### 3. Configuration - -1. Voluptuous schema present for [configuration validation](development_validation.md) -2. Voluptuous schema extends schema from component - (e.g., `hue.light.PLATFORM_SCHEMA` extends `light.PLATFORM_SCHEMA`) -3. Default parameters specified in voluptuous schema, not in `setup_platform(...)` -4. Your `PLATFORM_SCHEMA` should use as many generic config keys as possible from `homeassistant.const` -5. Never depend on users adding things to `customize` to configure behavior inside your platform. - -```python -import voluptuous as vol - -from homeassistant.const import CONF_FILENAME, CONF_HOST -from homeassistant.components.light import PLATFORM_SCHEMA -import homeassistant.helpers.config_validation as cv - -CONF_ALLOW_UNREACHABLE = 'allow_unreachable' -DEFAULT_UNREACHABLE = False - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_ALLOW_UNREACHABLE, - default=DEFAULT_UNREACHABLE): cv.boolean, - vol.Optional(CONF_FILENAME): cv.string, -}) -``` - -### 4. Setup Platform - -1. Verify that the passed in configuration (user/pass/host etc.) works. -2. Group your calls to `add_devices` if possible. -3. If the platform adds extra services, the format should be `.`. So if your integration's domain is "awesome_sauce" and you are making a light platform, you would register services under the `awesome_sauce` domain. Make sure that your services [verify permissions](auth_permissions.md#checking-permissions). - -### 5. Entity - -1. Extend the entity from the integration you're building a platform for. - - ```python - from homeassistant.components.light import Light - - class HueLight(Light): - ... - ``` - -2. Avoid passing in `hass` as a parameter to the entity. When the entity has been added to Home Assistant, `hass` will be set on the entity when the entity is added to Home Assistant. This means you can access `hass` as `self.hass` inside the entity. - -3. Do not call `update()` in constructor, use `add_entities(devices, True)` instead. -4. Do not do any I/O inside properties. Cache values inside `update()` instead. -5. When dealing with time, state and/or attributes should not contain relative time since something happened. Instead, it should store UTC timestamps. -6. Leverage the [entity lifecycle callbacks](entity_index.md#lifecycle-hooks) to attach event listeners or clean up connections. - -### 6. Communication with devices/services - -1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - - ```python - # bad - status = requests.get(url('/status')) - - # good - from phue import Bridge - bridge = Bridge(...) - status = bridge.status() - ``` - - [Tutorial on publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) \ No newline at end of file diff --git a/website/translated_docs/pl/creating_platform_example_light.md b/website/translated_docs/pl/creating_platform_example_light.md deleted file mode 100644 index 2eb9bdbd..00000000 --- a/website/translated_docs/pl/creating_platform_example_light.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: "" ---- - -[This page has moved.](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_light) - - diff --git a/website/translated_docs/pl/creating_platform_example_sensor.md b/website/translated_docs/pl/creating_platform_example_sensor.md deleted file mode 100644 index 97d1683d..00000000 --- a/website/translated_docs/pl/creating_platform_example_sensor.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: "" ---- - -[This page has moved.](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_sensor) - - diff --git a/website/translated_docs/pl/creating_platform_index.md b/website/translated_docs/pl/creating_platform_index.md deleted file mode 100644 index 4a8cab3f..00000000 --- a/website/translated_docs/pl/creating_platform_index.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Integration Platforms" -sidebar_label: "Platforms" ---- - -Home Assistant has various built-in integrations that abstract device types. There are [lights](entity_light.md), [switches](entity_switch.md), [covers](entity_cover.md), [climate devices](entity_climate.md), and [many more](entity_index.md). Your integration can hook into these integrations by creating a platform. You will need a platform for each integration that you are integrating with. - -To create a platform, you will need to create a file with the domain name of the integration that you are building a platform for. So if you are building a light, you will add a new file `light.py` to your integration folder. - -We have created two example integrations that should give you a look at how this works: - -- [Example sensor platform](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_sensor/): hello world of platforms. -- [Example light platform](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_light/): showing best practices. - -### Interfacing with devices - -One Home Assistant rule is that the integration should never interface directly with devices. Instead, it should interact with a third-party Python 3 library. This way, Home Assistant can share code with the Python community and keep the project maintainable. - -Once you have your Python library ready and published to PyPI, add it to the [manifest](creating_integration_manifest.md). It will now be time to implement the Entity base class that is provided by the integration that you are creating a platform for. - -Find your integration at the [entity index](entity_index.md) to see what methods and properties are available to implement. \ No newline at end of file diff --git a/website/translated_docs/pl/data_entry_flow_index.md b/website/translated_docs/pl/data_entry_flow_index.md deleted file mode 100644 index bd2e3b20..00000000 --- a/website/translated_docs/pl/data_entry_flow_index.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -title: Data Entry Flow -sidebar_label: Introduction ---- - -Data Entry Flow is a data entry framework that is part of Home Assistant. Data entry is done via data entry flows. A flow can represent a simple login form or a multi-step setup wizard for a component. A Flow Manager is managing all flows that are in progress and handles creation of new flows. - -Data Entry Flow is being used in Home Assistant to create config entries. - -## Flow Manager - -This is the class that manages the flows that are in progress. When instantiating one, you pass in two async callbacks: - -```python -async def async_create_flow(handler, context=context, data=data) -``` - -The manager delegates instantiating of config flow handlers to this async callback. This allows the parent of the manager to define their own way of finding handlers and preparing a handler for instantiation. For example, in the case of the config entry manager, it will make sure that the dependencies and requirements are setup. - -```python -async def async_finish_flow(flow, result) -``` - -This async callback is called when a flow is finished or aborted. i.e. `result['type'] in [RESULT_TYPE_CREATE_ENTRY, RESULT_TYPE_ABORT]`. The callback function can modify result and return it back, if the result type changed to `RESULT_TYPE_FORM`, the flow will continue running, display another form. - -If the result type is `RESULT_TYPE_FORM`, the result should like: - -```python -{ - # The result type of the flow - 'type': RESULT_TYPE_FORM, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # name of the step, flow.async_step_[step_id] will be called when form submitted - 'step_id': 'init', - # a voluptuous schema to build and validate user input - 'data_schema': vol.Schema(), - # an errors dict, None if no errors - 'errors': errors, - # a detail information about the step - 'description_placeholders': description_placeholders, -} -``` - -If the result type is `RESULT_TYPE_CREATE_ENTRY`, the result should like: - -```python -{ - # Data schema version of the entry - 'version': 2, - # The result type of the flow - 'type': RESULT_TYPE_CREATE_ENTRY, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # title and data as created by the handler - 'title': 'Some title', - 'result': { - 'some': 'data' - }, -} -``` - -If the result type is `RESULT_TYPE_ABORT`, the result should like: - -```python -{ - # The result type of the flow - 'type': RESULT_TYPE_ABORT, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # the abort reason - 'reason': 'already_configured', -} -``` - -## Flow Handler - -Flow handlers will handle a single flow. A flow contains one or more steps. When a flow is instantiated, the `FlowHandler.init_step` step will be called. Each step has three different possible results: "Show Form", "Abort" and "Create Entry". - -At a minimum, each flow handler will have to define a version number and a step. This doens't have to be `init`, as `async_create_flow` can assign `init_step` depends on diffreent workflow, for example in configuration, `context.source` will be use as `init_step`. - -The bare minimum config flow: - -```python -from homeassistant import data_entry_flow - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - # The schema version of the entries that it creates - # Home Assistant will call your migrate method if the version changes - # (this is not implemented yet) - VERSION = 1 - - async def async_step_user(self, user_input=None): - # Do something -``` - -### Show Form - -This result type will show a form to the user to fill in. You define the current step, the schema of the data (using voluptuous) and optionally a dictionary of errors. Title and description of the step will be provided via the translation file. Where this is defined depends on the context of the data entry flow. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema) - ) -``` - -After the user has filled in the form, the step method will be called again and the user input is passed in. Your step will only be called if the user input passes your data schema. When the user passes in data, you will have to do extra validation of the data. For example, you can verify that the passed in username and password are valid. - -If something is wrong, you can return a dictionary with errors. Each key in the error dictionary refers to a field name that contains the error. Use the key `base` if you want to show an error unrelated to a specific field. The specified errors need to refer to a key in a translation file. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # See next section on create entry usage - return self.create_entry(...) - - errors['base'] = 'auth_error' - - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema), - errors=errors - ) -``` - -#### Multi-step flows - -If the user input passes validation, you can again return one of the three return values. If you want to navigate the user to the next step, return the return value of that step: - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_init(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # Store info to use in next step - self.init_info = user_input - # Return the form of the next step - return await self.async_step_account() - - ... -``` - -### Create Entry - -When the result is "Create Entry", an entry will be created and passed to the parent of the flow manager. A success message is shown to the user and the flow is finished. You create an entry by passing a title and data. The title can be used in the UI to indicate to the user which entry it is. Data can be any data type, as long as it is JSON serializable. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - return self.create_entry( - title='Title of the entry', - data={ - 'something_special': user_input['username'] - } - ) -``` - -### Abort - -When a flow cannot be finished, you need to abort it. This will finish the flow and inform the user that the flow has finished. Reasons for a flow to not be able to finish can be that a device is already configured or not compatible with Home Assistant. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - return self.async_abort( - reason='not_supported' - ) -``` - -## Translations - -Data entry flows depend on translations for showing the text in the forms. It depends on the parent of a data entry flow manager where this is stored. - -## Initializing a config flow from an external source - -You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing a flow: - -```python -await flow_mgr.async_init('hue', context={'source': data_entry_flow.SOURCE_DISCOVERY}, data=discovery_info) -``` - -The config flow handler will not start with the `init` step. Instead, it will be instantiated with a step name equal to the source. The step should follow the same return values as a normal step. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` \ No newline at end of file diff --git a/website/translated_docs/pl/dev_101_config.md b/website/translated_docs/pl/dev_101_config.md deleted file mode 100644 index e91e5f31..00000000 --- a/website/translated_docs/pl/dev_101_config.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: "Using Config" ---- - -Based on where you are in the code, `config` can mean various things. - -### On the hass object - -On the hass object is an instance of the Config class. The Config class contains the users preferred units, the path to the config directory and which components are loaded. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config) - -### Config passed into component setup - -The `config` parameter passed to a component setup is a dictionary containing all of the user supplied configuration. The keys of the dictionary are the component names and the value is another dictionary with the component configuration. - -The object will have already been validated using your `CONFIG_SCHEMA` or `PLATFORM_SCHEMA` if available. If you have defined a `PLATFORM_SCHEMA`, all references to your component (ie `light 2:` etc) will have been changed to be accessible as a list under `config[DOMAIN]`. - -If your configuration file contains the following lines: - -```yaml -example: - host: paulusschoutsen.nl -``` - -Then in the setup method of your component you will be able to refer to `config['example']['host']` to get the value `paulusschoutsen.nl`. - -### Passed into platform setup - -The `config` parameter passed to a platform setup function is only the config for that specific platform. \ No newline at end of file diff --git a/website/translated_docs/pl/dev_101_events.md b/website/translated_docs/pl/dev_101_events.md deleted file mode 100644 index f6f38462..00000000 --- a/website/translated_docs/pl/dev_101_events.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: "Using Events" ---- - -The core of Home Assistant is driven by events. That means that if you want to respond to something happening, you'll have to respond to events. Most of the times you won't interact directly with the event system but use one of the [event listener helpers](https://dev-docs.home-assistant.io/en/master/api/helpers.html#module-homeassistant.helpers.event). - -The event system is very flexible. There are no limitations on the event type, as long as it's a string. Each event can contain data. The data is a dictionary that can contain any data as long as it's JSON serializable. This means that you can use number, string, dictionary and list. - -[List of events that Home Assistant fires.](https://www.home-assistant.io/docs/configuration/events/) - -## Firing events - -To fire an event, you have to interact with the event bus. The event bus is available on the Home Assistant instance as `hass.bus`. - -Example component that will fire an event when loaded. Note that custom event names are prefixed with the component name. - -```python -DOMAIN = 'example_component' - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - # Fire event example_component_my_cool_event with event data answer=42 - hass.bus.fire('example_component_my_cool_event', { - 'answer': 42 - }) - - # Return successful setup - return True -``` - -## Listening to events - -Most of the times you'll not be firing events but instead listen to events. For example, the state change of an entity is broadcasted as an event. - -```python -DOMAIN = 'example_component' - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - count = 0 - - # Listener to handle fired events - def handle_event(event): - nonlocal count - count += 1 - print('Answer {0} is: {1}'.format(count, event.data.get('answer'))) - - # Listen for when example_component_my_cool_event is fired - hass.bus.listen('example_component_my_cool_event', handle_event) - - # Return successful setup - return True -``` - -### Helpers - -Home Assistant comes with a lot of bundled helpers to listen to specific types of event. There are helpers to track a point in time, to track a time interval, a state change or the sun set. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/helpers.html#module-homeassistant.helpers.event) \ No newline at end of file diff --git a/website/translated_docs/pl/dev_101_hass.md b/website/translated_docs/pl/dev_101_hass.md deleted file mode 100644 index bc8d414e..00000000 --- a/website/translated_docs/pl/dev_101_hass.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: "Hass object" ---- - -While developing Home Assistant you will see a variable that is everywhere: `hass`. This is the Home Assistant instance that will give you access to all the various parts of the system. - -### The `hass` object - -The Home Assistant instance contains four objects to help you interact with the system. - -| Object | Description | -| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `hass` | This is the instance of Home Assistant. Allows starting, stopping and enqueing new jobs. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.HomeAssistant) | -| `hass.config` | This is the core configuration of Home Assistant exposing location, temperature preferences and config directory path. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config) | -| `hass.states` | This is the StateMachine. It allows you to set states and track when they are changed. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.StateMachine) | -| `hass.bus` | This is the EventBus. It allows you to trigger and listen for events. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.EventBus) | -| `hass.services` | This is the ServiceRegistry. It allows you to register services. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.ServiceRegistry) | - -### Where to find `hass` - -Depending on what you're writing, there are different ways the `hass` object is made available. - -**Component** -Passed into `setup(hass, config)` or `async_setup(hass, config)`. - -**Platform** -Passed into `setup_platform(hass, config, add_devices, discovery_info=None)` or `async_setup_platform(hass, config, async_add_devices, discovery_info=None)`. - -**Entity** -Available as `self.hass` once the entity has been added via the `add_devices` callback inside a platform. \ No newline at end of file diff --git a/website/translated_docs/pl/dev_101_index.md b/website/translated_docs/pl/dev_101_index.md deleted file mode 100644 index 9cbf54d8..00000000 --- a/website/translated_docs/pl/dev_101_index.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: "Development 101" -sidebar_label: Introduction ---- - -The goal of development 101 is to get you familiar with the basics of developing for Home Assistant. Before we start, please make sure you familiarize yourself with the [architecture](architecture_index.md). - -To get our code running inside Home Assistant we're going to create a custom component. The first step is to locate your config folder. You can find the path to your config folder by opening the Home Assistant frontend, click on the service developer tool icon. It's the path after the text "Path to configuration.yaml". - -Inside your configuration directory create a new folder called `custom_components`. It might be that one already exists, that's fine too. This is the folder that Home Assistant will look at when looking for custom code. - -> The Home Assistant API has two variants: a synchronous and an asynchronous version (asyncio). This development course will focus on the synchronous version. - -To verify that everything is working correctly, let's create a small Hello World component. To do so, create a file called `hello_world.py` in your custom components folder. Copy paste the following content to it: - -```python -# The domain of your component. Equal to the filename of your component. -DOMAIN = "hello_world" - - -def setup(hass, config): - """Setup the hello_world component.""" - # States are in the format DOMAIN.OBJECT_ID. - hass.states.set('hello_world.Hello_World', 'Works!') - - # Return boolean to indicate that initialization was successfully. - return True -``` - -Last step is to add `hello_world:` entry to your `configuration.yaml` file. - -```yaml -# Hello World component -hello_world: -``` - -After running `hass`, we should see log entries stating that `hello_world` component was loaded. What is more, additional state card shall appear within main panel. - -```log -2018-04-03 21:44:20 INFO (MainThread) [homeassistant.loader] Loaded hello_world from custom_components.hello_world -2018-04-03 21:44:20 INFO (MainThread) [homeassistant.setup] Setting up hello_world -``` - -![State card showing that Hello World component is working as intended.](/img/en/frontend/hello-world-state-card.png) \ No newline at end of file diff --git a/website/translated_docs/pl/dev_101_services.md b/website/translated_docs/pl/dev_101_services.md deleted file mode 100644 index 7bae113c..00000000 --- a/website/translated_docs/pl/dev_101_services.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: "Integration Services" -sidebar_label: "Custom Services" ---- - -Home Assistant provides ready-made services for a lot of things, but it doesn't always cover everything. Instead of trying to change Home Assistant, it is preferred to add it as a service under your own integration first. Once we see a pattern in these services, we can talk about generalizing them. - -This is a simple "hello world" example to show the basics of registering a service. To use this example, create the file `/custom_components/hello_service/__init__.py` and copy the below example code. - -Services can be called from automations and from the service "Developer tools" in the frontend. - -```python -DOMAIN = 'hello_service' - -ATTR_NAME = 'name' -DEFAULT_NAME = 'World' - - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - def handle_hello(call): - """Handle the service call.""" - name = call.data.get(ATTR_NAME, DEFAULT_NAME) - - hass.states.set('hello_service.hello', name) - - hass.services.register(DOMAIN, 'hello', handle_hello) - - # Return boolean to indicate that initialization was successfully. - return True -``` - -Load the integration by adding the following to your `configuration.yaml`. When your component is loaded, a new service should be available to call. - -```yaml -# configuration.yaml entry -hello_service: -``` - -Open the frontend and in the sidebar, click the first icon in the developer tool section. This will open the Call Service developer tool. On the right, find your service and click on it. This will automatically fill in the correct values. - -Pressing "Call Service" will now call your service without any parameters. This will cause your service to create a state with the default name 'World'. If you want to specify the name, you have to specify parameters. Add the following JSON as Service Data and press "Call Service again". - -```json -{ - "name": "Planet" -} -``` - -The service will now overwrite the previous state with "Planet". - -## Service descriptions - -Adding services is only useful if users know about them. In Home Assistant we use a `services.yaml` as part of your integration to describe the services. - -Services are published under the domain name of your integration, so in `services.yaml` we only use the service name as the base key. - -```yaml -# Example services.yaml entry - -set_speed: - # Description of the service - description: Sets fan speed. - # Different fields that your service accepts - fields: - # Key of the field - entity_id: - # Description of the field - description: Name(s) of the entities to set - # Example value that can be passed for this field - example: 'fan.living_room' - speed: - description: Speed setting - example: 'low' -``` \ No newline at end of file diff --git a/website/translated_docs/pl/dev_101_states.md b/website/translated_docs/pl/dev_101_states.md deleted file mode 100644 index d35379c7..00000000 --- a/website/translated_docs/pl/dev_101_states.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -title: "Using States" ---- - -Home Assistant keeps track of the states of entities in a state machine. The state machine has very few requirements: - -- Each state is related to an entity identified by an entity id. This id is made up of a domain and an object id. For example `light.kitchen_ceiling`. You can make up any combination of domain and object id, even overwriting existing states. -- Each state has a primary attribute that describes the state of the entity. In the case of a light this could be for example "on" and "off". You can store anything you want in the state, as long as it's a string (will be converted if it's not). -- You can store more information about an entity by setting attributes. Attributes is a dictionary that can contain any data that you want. The only requirement is that it's JSON serializable, so you're limited to numbers, strings, dictionaries and lists. - -[Description of the state object.](https://www.home-assistant.io/docs/configuration/state_object/) - -## Using states in your component - -This is a simple tutorial/example on how to create and set states. We will do our work in a component called "hello_state". The purpose of this component is to display a given text in the frontend. - -To get started, create the file `/custom_components/hello_state.py` and copy the below example code. - -```python -""" -Support for showing text in the frontend. - -For more details about this component, please refer to the documentation at -https://home-assistant.io/cookbook/python_component_basic_state/ -""" -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = 'hello_state' - -def setup(hass, config): - """Setup the Hello State component. """ - _LOGGER.info("The 'hello state' component is ready!") - - return True -``` - -1. In the file header we decided to add some details: A short description and the link to the documentation. -2. We want to do some logging. This means that we import the Python logging module and create an alias. -3. The component name is equal to the domain name. -4. The `setup` function will take care of the initialization of our component. The component will only write a log message. Keep in mind for later that you have several options for the severity: - -- `_LOGGER.info(msg)` -- `_LOGGER.warning(msg)` -- `_LOGGER.error(msg)` -- `_LOGGER.critical(msg)` -- `_LOGGER.exception(msg)` - -5. We return `True` if everything is ok. - -Add the component to your `configuration.yaml` file. - -```yaml -hello_state: -``` - -After a start or a restart of Home Assistant the component will create an entry in the log. - -```bash -16-03-12 14:16:42 INFO (MainThread) [custom_components.hello_state] The 'hello state' component is ready! -``` - -The next step is the introduction of configuration options. A user can pass configuration options to our component via `configuration.yaml`. To use them we'll use the passed in `config` variable to our `setup` method. - -```python -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = 'hello_state' - -CONF_TEXT = 'text' -DEFAULT_TEXT = 'No text!' - -def setup(hass, config): - """Set up the Hello State component. """ - # Get the text from the configuration. Use DEFAULT_TEXT if no name is provided. - text = config[DOMAIN].get(CONF_TEXT, DEFAULT_TEXT) - - # States are in the format DOMAIN.OBJECT_ID - hass.states.set('hello_state.Hello_State', text) - - return True -``` - -To use the latest feature of our component, update the entry in your `configuration.yaml` file. - -```yaml -hello_state: - text: 'Hello, World!' -``` - -Thanks to `DEFAULT_TEXT` variable the component will launch even if no `text:` field is used in the `configuration.yaml` file. Quite often there are variables which are required. It's important to check if all mandatory configuration variables are provided. If not, the setup should fail. We will use `voluptuous` as a helper to achieve this. The next listing shows the essential parts. - -```python -import voluptuous as vol - -import homeassistant.helpers.config_validation as cv - -CONFIG_SCHEMA = vol.Schema({ - DOMAIN: vol.Schema({ - vol.Required(CONF_TEXT): cv.string, - }) -}, extra=vol.ALLOW_EXTRA) -``` - -Now, when `text:` is missing from the config, Home Assistant will alert the user and not setup your component. - -After a start or a restart of Home Assistant the component will be visible in the frontend if the `configuration.yaml` file is up-to-date. - -

- -

- -In order to expose attributes for a platform, you will need to define a property called `device_state_attributes` on the entity class, which will return a dictionary of attributes: - - @property - def device_state_attributes(self): - """Return device specific state attributes.""" - return self._attributes - - -> Entities also have a similar property `state_attributes`, which normally doesn't need to be defined by new platforms. This property is used by base components to add standard sets of attributes to a state. Example: The light component uses `state_attributes` to add brightness to the state dictionary. If you are designing a new component, you should define `state_attributes` instead. - -To get your component included in the Home Assistant releases, follow the steps described in the [Submit your work](development_submitting.md) section. Basically you only need to move your component in the `homeassistant/component/` directory of your fork and create a Pull Request. \ No newline at end of file diff --git a/website/translated_docs/pl/development_catching_up.md b/website/translated_docs/pl/development_catching_up.md deleted file mode 100644 index 7f14f6d5..00000000 --- a/website/translated_docs/pl/development_catching_up.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: "Catching up with Reality" ---- - -If it's taking a while to develop your feature, and you want to catch up with what's in the current Home Assistant `dev` branch, you can use `git rebase`. This will pull the latest Home Assistant changes locally, rewind your commits, bring in the latest changes from Home Assistant, and replay all of your commits on top. - -> If you use the workflow below, it is important that you force push the update as described. Git might prompt you to do `git pull` first. Do **NOT** do that! It would mess up your commit history. - -```bash -# Run this from your feature branch -$ git fetch upstream dev # to pull the latest changes into a local dev branch -$ git rebase upstream/dev # to put those changes into your feature branch before your changes -``` - -If rebase detects conflicts, repeat this process until all changes have been resolved: - -1. `git status` shows you the file with the conflict; edit the file and resolve the lines between `<<<< | >>>>` -2. Add the modified file: `git add ` or `git add .` -3. Continue rebase: `git rebase --continue` -4. Repeat until you've resolved all conflicts - -After rebasing your branch, you will have rewritten history relative to your GitHub fork's branch. When you go to push you will see an error that your history has diverged from the original branch. In order to get your GitHub fork up-to-date with your local branch, you will need to force push, using the following command: - -```bash -# Run this from your feature branch -$ git push origin --force -``` - -Other workflows are covered in detail in the [Github documentation](https://help.github.com/articles/fork-a-repo/). Add an additional `remote` after you clone your fork. - -```bash -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -Then, `git pull --rebase upstream dev`. \ No newline at end of file diff --git a/website/translated_docs/pl/development_checklist.md b/website/translated_docs/pl/development_checklist.md deleted file mode 100644 index 0d1652cd..00000000 --- a/website/translated_docs/pl/development_checklist.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: "Development Checklist" -sidebar_label: Introduction ---- - - -Before you commit any changes, check your work against these requirements: - -- All communication to external devices or services must be wrapped in an external Python library hosted on [pypi](https://pypi.python.org/pypi). -- New dependencies are added to `requirements_all.txt` (if applicable), using `python3 -m script.gen_requirements_all` -- New codeowners are added to `CODEOWNERS` (if applicable), using `python3 -m script.hassfest` -- The `.coveragerc` file is updated to exclude your platform if there are no tests available or your new code uses a third-party library for communication with the device, service, or sensor -- Documentation is developed for [home-assistant.io](https://home-assistant.io/) - - Visit the [website documentation](https://www.home-assistant.io/developers/documentation/) for more information about contributing to [home-assistant.io](https://github.com/home-assistant/home-assistant.github.io). \ No newline at end of file diff --git a/website/translated_docs/pl/development_environment.md b/website/translated_docs/pl/development_environment.md deleted file mode 100644 index 9e0bc03c..00000000 --- a/website/translated_docs/pl/development_environment.md +++ /dev/null @@ -1,117 +0,0 @@ ---- -title: "Set up Development Environment" ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example CentOS would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Due to Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run - -```bash -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is set up, perform install as for Linux. - -```bash -$ sudo apt-get update -$ sudo apt-get install python3-pip python3-dev python3-venv -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```bash -$ mkdir -p ../config -$ hass -c ../config -``` - -### Developing on OS X - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 autoconf -``` - -Then install ffmpeg: - -```bash -$ brew install ffmpeg -``` - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv venv -$ source venv/bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```bash -$ hass -``` - -## Logging - -By default logging in Home Assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` \ No newline at end of file diff --git a/website/translated_docs/pl/development_guidelines.md b/website/translated_docs/pl/development_guidelines.md deleted file mode 100644 index 0383618a..00000000 --- a/website/translated_docs/pl/development_guidelines.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: "Style guidelines" ---- - -Home Assistant enforces strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. We automatically test every pull request as part of the linting process. - -Summary of the most relevant points: - -- Line length is limited to 79 characters (see below). -- Use 4 spaces per indentation level. We don't use tabs. -- Comments should be full sentences and end with a period. -- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered. -- Constants and the content of lists and dictionaries should be in alphabetical order. -- Avoid trailing whitespace but surround binary operators with a single space. -- Line separator should be set to `LF`. - -The maximum line length comes directly from the [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/#maximum-line-length), and is also used by the Python standard library. All code must pass these linting checks, and no exceptions will be made. There have already been numerous requests to increase the maximum line length, but after evaluating the options, the Home Assistant maintainers have decided to stay at 79 characters. This decision is final. - -Those points may require that you adjust your IDE or editor settings. - -## Our recommendations - -For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code unified. - -### Quotes - -Use single quotes `'` for single word and `"` for multiple words or sentences. - -```python -ATTR_WATERLEVEL = 'level' -CONF_ATTRIBUTION = "Data provided by the WUnderground weather service" -SENSOR_TYPES = { - 'alerts': ['Alerts', None], -} -``` - -### File headers - -The docstring in the file header should describe what the file is about. - -```python -"""Support for MQTT lights.""" -``` - -### Log messages - -There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. Try to avoid brackets and additional quotes around the output to make it easier for users to parse the log. A widely style is shown below but you are free to compose the messages as you like. - -```python -_LOGGER.error("No route to device: %s", self._resource) -``` - -```bash -2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18 -``` - -Don't print out wrong API keys, tokens, usernames, or passwords. Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` in anything else. - -### Ordering of imports - -Instead of order the imports manually, use [`isort`](https://github.com/timothycrosley/isort). - -```bash -$ pip3 install isort -$ isort homeassistant/components/sensor/fixer.py -``` - -### Use new style string formatting - -Prefer [new style string formatting](https://www.python.org/dev/peps/pep-3101/) over old. - -```python -"{} {}".format('New', 'style') -"%s %s" % ('Old', 'style') -``` - -Except when doing logging here the format is: - -```python -_LOGGER.info("Can't connect to the webservice %s at %s", string1, string2) -``` \ No newline at end of file diff --git a/website/translated_docs/pl/development_index.md b/website/translated_docs/pl/development_index.md deleted file mode 100644 index d0557fd3..00000000 --- a/website/translated_docs/pl/development_index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: "Starting with Development" -sidebar_label: Introduction ---- - -Home Assistant is built from the ground up to be easily extensible using integrations. In this section, we're focusing on how to develop integrations. - -Before you start, make sure that you have read up on the [Home Assistant architecture](architecture_index.md) so that you are familiar with the concepts that make up Home Assistant. - -If you run into trouble following this documentation, don't hesitate to join our #devs_backend channel on [Discord](https://www.home-assistant.io/join-chat/). \ No newline at end of file diff --git a/website/translated_docs/pl/development_submitting.md b/website/translated_docs/pl/development_submitting.md deleted file mode 100644 index 5f0bac56..00000000 --- a/website/translated_docs/pl/development_submitting.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -title: "Submit your work" ---- - -> Always base your Pull Requests of of the current **`dev`** branch, not `master`. - -Submit your improvements, fixes, and new features to Home Assistant one at a time, using GitHub [Pull Requests](https://help.github.com/articles/using-pull-requests). Here are the steps: - -1. From your fork's dev branch, create a new branch to hold your changes: - - `git checkout -b some-feature` - -2. Make your changes, create a [new platform](creating_platform_index.md), develop a [new component](creating_component_index.md), or fix [issues](https://github.com/home-assistant/home-assistant/issues). - -3. [Test your changes](development_testing.md) and check for style violations. - -4. If everything looks good according to these [musts](development_checklist.md), commit your changes: - - `git add .` - - `git commit -m "Add some-feature"` - - - Write a meaningful commit message and not only `Update` or `Fix`. - - Use a capital letter to start with your commit message. - - Don't prefix your commit message with `[bla.bla]` or `platform:`. - - Consider adding tests to ensure that your code works. - -5. Push your committed changes back to your fork on GitHub: - - `git push origin HEAD` - -6. Follow [these steps](https://help.github.com/articles/creating-a-pull-request/) to create your pull request. - - - On GitHub, navigate to the main page of the Home Assistant repository. - - In the "Branch" menu, choose the branch that contains your commits (from your fork). - - To the right of the Branch menu, click **New pull request**. - - Use the base branch dropdown menu to select the branch you'd like to merge your changes into, then use the compare branch drop-down menu to choose the topic branch you made your changes in. Make sure the Home Assistant branch matches with your forked branch (`dev`) else you will propose ALL commits between branches. - - Type a title and complete the provided description for your pull request. - - Click **Create pull request**. - -7. Check for comments and suggestions on your pull request and keep an eye on the [CI output](https://travis-ci.org/home-assistant/home-assistant/). \ No newline at end of file diff --git a/website/translated_docs/pl/development_testing.md b/website/translated_docs/pl/development_testing.md deleted file mode 100644 index 2b57f7e1..00000000 --- a/website/translated_docs/pl/development_testing.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: "Testing your code" ---- - -As it states in the [Style guidelines section](development_guidelines.md) all code is checked to verify the following: - -- All the unit tests pass -- All code passes the checks from the linting tools - -Local testing is done using Tox, which has been installed as part of running `script/setup` in the [virtual environment](development_environment.md). To start the tests, activate the virtual environment and simply run the command: - -```bash -$ tox -``` - -**Important:** Run `tox` before you create your pull request to avoid annoying fixes. - -Running Tox will run unit tests against the locally available Pythons, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one tox target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py36` runs unit tests only on Python 3.6. - -Tox uses virtual environments under the hood to create isolated testing environments. The tox virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell Tox to recreate the virtual environments. - -OSX users may see an `Error creating virtualenv` when runnng `tox`. If this occurs, install the [tox-venv](https://pypi.org/project/tox-venv/) package using the command `pip install tox-venv` and try again. - -### Adding new dependencies to test environment - -If you are working on tests for a component or platform and you need the dependencies available inside the Tox environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments. - -### Running single tests using Tox - -You can pass arguments via Tox to py.test to be able to run single test suites or test files. Replace `py36` with the Python version that you use. - -```bash -# Stop after the first test fails -$ tox -e py36 -- tests/test_core.py -x -# Run test with specified name -$ tox -e py36 -- tests/test_core.py -k test_split_entity_id -# Fail a test after it runs for 2 seconds -$ tox -e py36 -- tests/test_core.py --timeout 2 -# Show the 10 slowest tests -$ tox -e py36 -- tests/test_core.py --duration=10 -``` - -### Testing outside of Tox - -Running tox will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without Tox, you'll need to install the test dependencies into your Python environment: - -```bash -$ pip3 install -r requirements_test_all.txt -c homeassistant/package_constraints.txt -``` - -Now that you have all test dependencies installed, you can run tests on individual files: - -```bash -$ flake8 homeassistant/core.py -$ pylint homeassistant/core.py -$ pydocstyle homeassistant/core.py -$ py.test tests/test_core.py -``` - -You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script: - -```bash -$ script/lint -``` - -### Preventing Linter Errors - -Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them! - -```bash -$ pip3 install flake8 flake8-docstrings -$ flake8 --install-hook=git -``` - -The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8. - -### Notes on PyLint and PEP8 validation - -If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member. \ No newline at end of file diff --git a/website/translated_docs/pl/development_typing.md b/website/translated_docs/pl/development_typing.md deleted file mode 100644 index 81f153cd..00000000 --- a/website/translated_docs/pl/development_typing.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: "Adding type hints to your code" ---- - -Type hints in Python are static annotations of variables and functions, to let humans more easily understand the code. See the standard library [docs](https://docs.python.org/3/library/typing.html) and this PyCascades 2018 [talk](https://youtu.be/zKre4DKAB30). - -Type hints are not required for all modules at the moment in Home Assistant, but we aim to have complete coverage of the core modules. - -Adding type hints to an existing codebase can be a daunting task. To speed this up and help developers doing this, Instagram made the [`monkeytype`](https://pypi.org/project/MonkeyType/) program. It will analyze calls during runtime and try to assign the correct type hints to the code. - -See [this instagram blog post](https://instagram-engineering.com/let-your-code-type-hint-itself-introducing-open-source-monkeytype-a855c7284881) for a description of the workflow involved to use the monkeytype program. - -We've added a script to start a run of our test suite or a test module and tell the `monkeytype` program to analyze the run. - -### Basic workflow - -1. Run `script/monkeytype tests/path/to/your_test_module.py`. -2. Run `monkeytype stub homeassistant.your_actual_module`. -3. Look at output from the monkeytyped typing stub. If not totally bad, apply the stub to your module. You most likely will need to manually edit the typing in the last step. -4. Run `monkeytype apply homeassistant.your_actual_module`. -5. Check the diff and manually correct the typing if needed. Commit, push the branch and make a PR. - -**Note:** Applying a monkeytyped stub to a module that has existing typing annotations might error and not work. This tool is most useful for totally untyped modules. \ No newline at end of file diff --git a/website/translated_docs/pl/development_validation.md b/website/translated_docs/pl/development_validation.md deleted file mode 100644 index 9e7770a7..00000000 --- a/website/translated_docs/pl/development_validation.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: "Validate the input" ---- - -The `configuration.yaml` file contains the configuration options for components and platforms. We use [voluptuous](https://pypi.python.org/pypi/voluptuous) to make sure that the configuration provided by the user is valid. Some entries are optional or could be required to set up a platform or a component. Others must be a defined type or from an already-defined list. - -We test the configuration to ensure that users have a great experience and minimize notifications if something is wrong with a platform or component setup before Home Assistant runs. - -Besides [voluptuous](https://pypi.python.org/pypi/voluptuous) default types, many custom types are available. For an overview, take a look at the [config_validation.py](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/config_validation.py) helper. - -- Types: `string`, `byte`, and `boolean` -- Entity ID: `entity_id` and `entity_ids` -- Numbers: `small_float` and `positive_int` -- Time: `time`, `time_zone` -- Misc: `template`, `slug`, `temperature_unit`, `latitude`, `longitude`, `isfile`, `sun_event`, `ensure_list`, `port`, `url`, and `icon` - -To validate platforms using [MQTT](https://www.home-assistant.io/components/mqtt/), `valid_subscribe_topic` and `valid_publish_topic` are available. - -Some things to keep in mind: - -- Use the constants defined in `const.py` -- Import `PLATFORM_SCHEMA` from the integration you are integrating with and extend it. -- Preferred order is `required` first and `optional` second -- Default values for optional configuration keys need to be valid values. Don't use a default which is `None` like `vol.Optional(CONF_SOMETHING, default=None): cv.string`, set the default to `default=''` if required. - -### Snippets - -This section contains snippets for the validation we use. - -#### Default name - -It's common to set a default for a sensor if the user doesn't provide a name to use. - -```python -DEFAULT_NAME = 'Sensor name' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, -``` - -#### Limit the values - -You might want to limit the user's input to a couple of options. - -```python -DEFAULT_METHOD = 'GET' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): vol.In(['POST', 'GET']), -``` - -#### Port - -All port numbers are from a range of 1 to 65535. - -```python -DEFAULT_PORT = 993 - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, -``` - -#### Lists - -If a sensor has a pre-defined list of available options, test to make sure the configuration entry matches the list. - -```python -SENSOR_TYPES = { - 'article_cache': ('Article Cache', 'MB'), - 'average_download_rate': ('Average Speed', 'MB/s'), -} - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_MONITORED_VARIABLES, default=[]): - vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), -``` \ No newline at end of file diff --git a/website/translated_docs/pl/device_registry_index.md b/website/translated_docs/pl/device_registry_index.md deleted file mode 100644 index 394002ea..00000000 --- a/website/translated_docs/pl/device_registry_index.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Device Registry -sidebar_label: Introduction ---- - -The device registry is a registry where Home Assistant keeps track of devices. A device is represented in Home Assistant via one or more entities. For example, a battery-powered temperature and a humidity sensor might expose entities for temperature, humidity and battery level. - -![Device registry overview](/img/en/device_registry/overview.png) - -## What is a device? - -A device in Home Assistant represents a physical device that has its own control unit. The control unit itself does not have to be smart, but it should be in control of what happens. For example, an Ecobee thermostat with 4 room sensors equals 5 devices in Home Assistant, one for the thermostat including all sensors inside it, and one for each sensor. - -If you connect a sensor to another device to read some of its data, it should still be represented as two different devices. The reason for this is that the sensor could be moved to read the data of another device. - -> Although not currently available, we could consider offering an option to users to merge devices. - -## Device properties - -| Attribute | Description | -| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| id | Unique ID of device (generated by Home Assistant) | -| name | Name of this device | -| connections | A set of tuples of `(connection_type, connection identifier)`. Connection types are defined in the device registry module. | -| identifiers | Set of identifiers. They identify the device in the outside world. An example is a serial number. | -| manufacturer | The manufacturer of the device. | -| model | The model of the device. | -| config_entries | Config entries that are linked to this device. | -| sw_version | The firmware version of the device. | -| via_hub | Identifier of a device that routes messages between this device and Home Assistant. Examples of such devices are hubs. This is used to show device topology in Home Assistant. | -| area_id | The Area which the device is placed in. | - -## Defining devices - -> Entity device info is only read if the entity is loaded via a [config entry](config_entries_index.md). - -Each entity is able to define a device via the `device_info` property. This property is read when an entity is added to Home Assistant via a config entry. A device will be matched up with an existing device via supplied identifiers and connections, like serial numbers or MAC addresses. - -```python -# Inside a platform -class HueLight(LightEntity): - - @property - def device_info(self): - return { - 'identifiers': { - # Serial numbers are unique identifiers within a specific domain - (hue.DOMAIN, self.unique_id) - }, - 'name': self.name, - 'manufacturer': self.light.manufacturername, - 'model': self.light.productname, - 'sw_version': self.light.swversion, - 'via_hub': (hue.DOMAIN, self.api.bridgeid), - } - -``` - -Components are also able to register devices in the case that there are no entities representing them. An example is a hub that communicates with the lights. - -```python -# Inside a component -from homeassistant.helpers import device_registry as dr - -device_registry = await dr.async_get_registry(hass) - -device_registry.async_get_or_create( - config_entry=entry.entry_id, - connections={ - (dr.CONNECTION_NETWORK_MAC, config.mac) - }, - identifiers={ - (DOMAIN, config.bridgeid) - }, - manufacturer='Signify', - name=config.name, - model=config.modelid, - sw_version=config.swversion, -) -``` \ No newline at end of file diff --git a/website/translated_docs/pl/documentation_create_page.md b/website/translated_docs/pl/documentation_create_page.md deleted file mode 100644 index e1669a55..00000000 --- a/website/translated_docs/pl/documentation_create_page.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: "Create a new page" ---- - -For a platform or component page, the fastest way is to make a copy of an existing page and edit it. The [Component overview](https://www.home-assistant.io/components/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages. - -Please honor the [Standards](documentation_standards.md) we have for the documentation. - -If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers. - -```text ---- -layout: page -title: "Awesome Sensor" -description: "home-assistant.io web presence" -date: 2015-06-17 08:00 -sidebar: true -comments: false -sharing: true -footer: true -ha_release: "0.38" -ha_category: Sensor -ha_iot_class: "Local Polling" -ha_qa_scale: silver ---- - -Content... Written in markdown. - -### {% linkable_title Linkable Header %} -... -``` - -Please keep in mind that if the `date:` entry is in the future then the page will not show up. - -Additional keys for the file header: - -- `logo`: Please check the separate section below. -- `ha_release`: The release when the integration was included, e.g., "0.38". If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`. -- `ha_category`: This entry is used to group the integration on the [Components overview](https://www.home-assistant.io/components/). -- `ha_iot_class`: [IoT class](https://www.home-assistant.io/blog/2016/02/12/classifying-the-internet-of-things) is the classifier for the device's behavior. -- `ha_qa_scale`: [Quality scale](https://www.home-assistant.io/docs/quality_scale/) is the representation of the integration's quality. - -There are [pre-defined variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation. - -A couple of points to remember: - -- Document the needed steps to retrieve API keys or access token for the third party service or device if needed. -- Add screenshots to support the user where it makes sense. -- Add the type of the device(s) (incl. firmware) you have tested when you know that there are multiple out there. - -### Configuration - -Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file. - -The **Configuration Variables** section must use the `{% configuration %} ... {% endconfiguration %}` tag. - -```text -{% configuration %} -api_key: - description: The API key to access the service. - required: true - type: string -name: - description: Name to use in the frontend. - required: false - default: The default name to use in the frontend. - type: string -monitored_conditions: - description: Conditions to display in the frontend. - required: true - type: map - keys: - weather: - description: A human-readable text summary. - temperature: - description: The current temperature. -{% endconfiguration %} -``` - -Available keys: - -- **`description:`**: That the variable is about. -- **`required:`**: If the variable is required. - -```text -required: true #=> Required -required: false #=> Optional -required: inclusive #=> Inclusive -required: exclusive #=> Exclusive -required: any string here #=> Any string here -``` - -- **`type:`**: The type of the variable. Allowed entries: `boolean`, `string`, `integer`, `float`, `time`, `template`, `device_class`, `icon` or `map`/`list` (for a list of entries). For multiple possibilities use `[string, integer]`. If you use `map`/`list` then should define `keys:` (see the [`template` sensor](https://www.home-assistant.io/components/sensor.template/) for an example). If you use `boolean`, then `default:` must be defined. -- **`default:`**: The default value for the variable. - -### Embedding Code - -You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in back-ticks. - -When you're writing code that is to be executed on the terminal, prefix it with `$`. - -### Templates - -For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) [Jinja](http://jinja.pocoo.org/) is used. Check the [Documentation Standards](documentation_standards.md) for further details. - -If you are don't escape templates then they will be rendered and appear blank on the website. - -### HTML - -The direct usage of HTML is supported but not recommended. The note boxes are an exception. - -```html -

- You need to enable telnet on your router. -

-``` - -### Images, icons and logos - -The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent. - -| Type | Location | -|:----------- |:------------------------------ | -| logos | source/images/supported_brands | -| blog | source/images/blog | -| screenshots | source/images/components | - -Not everything (product, component, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/). - -### Linking From The Sidebar - -If you are adding a new page that requires linking from the sidebar, you need to edit the `docs_navigation.html` file in `source/_includes/asides/docs_navigation.html`. \ No newline at end of file diff --git a/website/translated_docs/pl/documentation_index.md b/website/translated_docs/pl/documentation_index.md deleted file mode 100644 index d196169c..00000000 --- a/website/translated_docs/pl/documentation_index.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: "Documentation" ---- - -The user documentation is located at . This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. You work on your change and propose it via a Pull Request (PR). - -Once you've created a Pull Request (PR), you can see a preview of the proposed changes by clicking *Details* against Netlify checker in the checkers section of the PR as soon as deployment is complete. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process of working on the website is no different from working on Home Assistant itself. - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.3.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` (You might have to run this command as `sudo`). -- Fork the home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.io). -- In your home-assistant.io root directory, run `$ bundle` to install the gems you need. - -- Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` - -- Shortcut for Debian/Ubuntu: `$ sudo apt-get install ruby ruby-dev ruby-bundler ruby-json g++ zlib1g-dev && bundle` - -Then you can work on the documentation: - -- Run `bundle exec rake generate` to generate the very first preview. This will take a couple of minutes. -- Create/edit/update a page. The components/platforms documentation is located in `source/_components/`. `source/_docs/` contains the Home Assistant documentation itself. -- Test your changes to home-assistant.io locally: run `bundle exec rake preview` and navigate to . While this command is working, any changes to a file are automatically detected and will update the affected pages. You will have to manually reload them in the browser though. -- Create a Pull Request (PR) against the **next** branch of home-assistant.io if your documentation is a new feature, platform, or component. -- Create a Pull Request (PR) against the **current** branch of home-assistant.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -The site generated by `bundle exec rake` is only available locally. If you are developing on a headless machine, use port forwarding: - -```bash -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` - -## Speeding up site generation - -Every release we post long changelogs to the website. This slows down generation of the website significantly! We include some tools to temporarily exclude components and blog posts that you're not working on out of the way. - -```bash -bundle exec rake isolate[filename-of-blogpost-or-component] -``` - -When you're done working on the site, run the following command to move the pages back again: - -```bash -bundle exec rake integrate -``` \ No newline at end of file diff --git a/website/translated_docs/pl/documentation_standards.md b/website/translated_docs/pl/documentation_standards.md deleted file mode 100644 index d0ae54d1..00000000 --- a/website/translated_docs/pl/documentation_standards.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: "Standards" ---- - -To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation. - -## General Documentation - -* The language of the documentation should be American-English. -* Don't put two spaces after a period and avoid the "Oxford comma". -* There is no limit for the line length. You are allowed to write in a flowing text style. This will make it easier to use the GitHub online editor in the future. -* Be objective and not gender favoring, polarizing, race related or religion inconsiderate. -* The case of brand names, services, protocols, components and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select". -* All headings should use the `{% linkable_title %}` tag. -* Do not use ALL CAPITALS for emphasis - use italics instead. - -## Component and Platform Pages - -* The **Configuration Variables** section must use the `{% configuration %}` tag. -* Configuration variables must document the requirement status (`false` or `true`). -* Configuration variables must document the default value, if any. -* Configuration variables must document the accepted value types (see [Configuration variables details](documentation_create_page.md#configuration)). - * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`). -* Use YAML sequence syntax in the sample code if it is supported. -* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated. - * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`. - * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note. -* Component and platform names should be a link to their respective documentation pages. - -Example configuration block - -```yaml -{% configuration %} -some_key: - description: This is a description of what this key is for. - required: false - type: string - default: Optional default value - leave out if there isn't one -{% endconfiguration %} -``` - -## Templates - -* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the `{% raw %}` tag. -* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`. -* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)): - * `friendly_name` - * Single-line templates: - * `value_template` - * `level_template` - * `icon_template` - * Children of `data_template` -* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks): - * Strings inside of templates: - * States - * Entity IDs - * `unit_of_measurement` -* No whitespace around pipe character (`|`) for Jinja2 filters. -* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}). -* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}). -* Do not quote values for: - * `device_class` - * `platform` - * `condition` - * `service` - -## Renaming Pages - -It can happen that a component or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old component/platform name, to the page in a [note](/developers/documentation/create_page/#html). - -```text ---- -... -redirect_from: /getting-started/android/ ---- -``` - -Adding a redirect also applies if you move content around in the [documentation](/docs/). - -## Single vs. Double Quotation Marks - -Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required). - -### Examples - -#### Double Quotes Outside, Single Quotes Inside (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}" -``` - -#### Single Quotes Outside, Double Quotes Inside (Invalid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}' -``` - -#### Multi-Line Template (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: >- - {% if trigger.to_state.name == 'Dale\'s Bedroom' %} - Someone's in your base, killing your noobs! - {% else %} - It's just another door. - {% endif %} -``` \ No newline at end of file diff --git a/website/translated_docs/pl/entity_air_quality.md b/website/translated_docs/pl/entity_air_quality.md deleted file mode 100644 index 81c10f5c..00000000 --- a/website/translated_docs/pl/entity_air_quality.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Air Quality Entity -sidebar_label: Air Quality ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ---------------------------- | ----- | ------------ | --------------------------------------------- | -| particulate_matter_2_5 | float | **Required** | The particulate matter 2.5 (<= 2.5 μm) level. | -| particulate_matter_10 | float | **Required** | The particulate matter 10 (<= 10 μm) level. | -| particulate_matter_0_1 | float | `None` | The particulate matter 0.1 (<= 0.1 μm) level. | -| air_quality_index | float | `None` | The Air Quality Index (AQI). | -| ozone | float | `None` | The O3 (ozone) level. | -| carbon_monoxide | float | `None` | The CO (carbon monoxide) level. | -| carbon_dioxide | float | `None` | The CO2 (carbon dioxide) level. | -| sulphur_dioxide | float | `None` | The SO2 (sulphur dioxide) level. | -| nitrogen_oxide | float | `None` | The N2O (nitrogen oxide) level. | -| nitrogen_monoxide | float | `None` | The NO (nitrogen monoxide) level. | -| nitrogen_dioxide | float | `None` | The NO2 (nitrogen dioxide) level. | -| volatile_organic_compounds | float | `None` | The volatile organic compounds (VOC) level. | - -Properties have to follow the units defined in the `unit_system`. \ No newline at end of file diff --git a/website/translated_docs/pl/entity_alarm_control_panel.md b/website/translated_docs/pl/entity_alarm_control_panel.md deleted file mode 100644 index 9dc91192..00000000 --- a/website/translated_docs/pl/entity_alarm_control_panel.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Alarm Control Panel Entity -sidebar_label: Alarm Control Panel ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ----------- | ------ | ------------ | --------------------------------------------------------- | -| state | string | **Required** | One of the states listed in the **states** section. | -| code_format | string | `None` | One of the states listed in the **code formats** section. | -| changed_by | string | `None` | Last change triggered by. | - -### States - -| Value | Description | -| ---------------------- | ------------------------------------------- | -| `disarmed` | The alarm is disarmed (`off`). | -| `armed_home` | The alarm is armed in home mode. | -| `armed_away` | The alarm is armed in away mode. | -| `armed_night` | The alarm is armed in night mode. | -| `armed_custom_bypass`  | The alarm is armed in bypass mode. | -| `pending` | The alarm is pending (towards `triggered`). | -| `arming` | The alarm is arming. | -| `disarming` | The alarm is disarming. | -| `triggered` | The alarm is triggered. | - -### Code Formats - -| Value | Description | -| ------ | ------------------------------------------------- | -| None | No code required. | -| Number | Code is a number (Shows ten-key pad on frontend). | -| Any | Code is a string. | - -## Methods - -### Alarm Disarm - -Send disarm command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_disarm(self, code=None) -> None: - """Send disarm command.""" - - async def async_alarm_disarm(self, code=None) -> None: - """Send disarm command.""" -``` - -### Alarm Arm Home - -Send arm home command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_home(self, code=None) -> None: - """Send arm home command.""" - - def async_alarm_arm_home(self, code=None) -> None: - """Send arm home command.""" -``` - -### Alarm Arm Away - -Send arm away command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_away(self, code=None) -> None: - """Send arm away command.""" - - def async_alarm_arm_away(self, code=None) -> None: - """Send arm away command.""" -``` - -### Alarm Arm Night - -Send arm night command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_night(self, code=None) -> None: - """Send arm night command.""" - - def async_alarm_arm_night(self, code=None) -> None: - """Send arm night command.""" -``` - -### Alarm Trigger - -Send alarm trigger command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_trigger(self, code=None) -> None: - """Send alarm trigger command.""" - - def async_alarm_trigger(self, code=None) -> None: - """Send alarm trigger command.""" -``` - -### Alarm Custom Bypass - -Send arm custom bypass command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_custom_bypass(self, code=None) -> None: - """Send arm custom bypass command.""" - - def async_alarm_arm_custom_bypass(self, code=None) -> None: - """Send arm custom bypass command.""" -``` \ No newline at end of file diff --git a/website/translated_docs/pl/entity_binary_sensor.md b/website/translated_docs/pl/entity_binary_sensor.md deleted file mode 100644 index 1a791ddb..00000000 --- a/website/translated_docs/pl/entity_binary_sensor.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Binary Sensor Entity -sidebar_label: Binary Sensor ---- - -A binary sensor is a sensor that can only have two states. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------ | ------- | ------------ | -------------------------------------------- | -| is_on | boolean | **Required** | If the binary sensor is currently on or off. | -| device_class | string | `None` | Type of binary sensor. | - -### Available device classes - -| Value | Description | -| ------------ | ------------------------------------------------------ | -| battery | On means low, Off means normal. | -| cold | On means cold, Off means normal. | -| connectivity | On means connected, Off means disconnected. | -| door | On means open, Off means closed. | -| garage_door | On means open, Off means closed. | -| gas | On means gas detected, Off means no gas (clear). | -| heat | On means hot, Off means normal. | -| light | On means light detected, Off means no light. | -| lock | On means open (unlocked), Off means closed (locked). | -| moisture | On means wet, Off means dry. | -| motion | On means motion detected, Off means no motion (clear). | -| moving | On means moving, Off means not moving (stopped). | -| occupancy | On means occupied, Off means not occupied (clear). | -| opening | On means open, Off means closed. | -| plug | On means plugged in, Off means unplugged. | -| power | On means power detected, Off means no power. | -| presence | On means home, Off means away. | -| problem | On means problem detected, Off means no problem (OK). | -| safety | On means unsafe, Off means safe. | -| smoke | On means smoke detected, Off means no smoke (clear). | -| sound | On means sound detected, Off means no sound (clear). | -| vibration | On means vibration detected, Off means no vibration. | -| window | On means open, Off means closed. | \ No newline at end of file diff --git a/website/translated_docs/pl/entity_climate.md b/website/translated_docs/pl/entity_climate.md deleted file mode 100644 index 477e1bcd..00000000 --- a/website/translated_docs/pl/entity_climate.md +++ /dev/null @@ -1,230 +0,0 @@ ---- -title: Climate Entity -sidebar_label: Climate ---- - -> A climate entity is a device that controls temperature, humidity, or fans, such as A/C systems and humidifiers. Derive entity platforms from [`homeassistant.components.climate.ClimateDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/climate/__init__.py) - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------------------- | ---------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | -| current_fan_mode | string | None | Returns the current fan mode. | -| current_hold_mode | string | None | The current hold mode, e.g., home, away, temp. | -| current_humidity | float | None | The current humidity. | -| current_operation | string | None | The current operation (e.g. heat, cool, idle). Used to determine `state`. | -| current_swing_mode | string | None | Returns the fan setting. | -| current_temperature | float | None | The current temperature. | -| fan_list | list | None | Returns the list of available fan modes. | -| is_aux_heat_on | bool | None | Returns True if an auxiliary heater is on. | -| is_away_mode_on | bool | None | Return true if away mode is on. | -| is_on | bool | None | Returns True if device is on. Used to determine `state`. | -| max_humidity | int | `DEFAULT_MAX_HUMIDITY` (value == 99) | Returns the maximum humidity. | -| max_temp | int | `DEFAULT_MAX_TEMP` (value == 35) | Returns the maximum temperature. | -| min_humidity | int | `DEFAULT_MIN_HUMIDITY` (value == 30) | Returns the minimum humidity. | -| min_temp | int | `DEFAULT_MIN_TEMP` (value == 7) | Returns the minimum temperature. | -| operation_list | list | None | List of available operation modes. | -| precision | float | PRECISION_WHOLE | The precision of the temperature in the system: tenths for TEMP_CELSIUS, whole number otherwise. | -| state | string | None | Returns the current state. | -| state_attributes | dictionary | N/A | The optional state attributes: current temperature, minimum temperature, maximum temperature, and target temperature. | -| supported_features | list | `NotImplementedError()` | Returns list of supported features. | -| swing_list | list | None | Returns the list of available swing modes. | -| target_humidity | float | None | The target humidity. | -| target_temperature | float | None | The temperature currently set to be reached. | -| target_temperature_high | float | None | The upper bound target temperature | -| target_temperature_low | float | None | The lower bound target temperature | -| target_temperature_step | float | None | The supported step of target temperature | -| temperature_unit | string | `NotImplementedError` | The unit of temperature measurement for the system (e.g. Celsius). | - -### States - -| Name | Description | -| ---------------- | ------------------------------ | -| STATE_HEAT | The device is set to heat. | -| STATE_COOL | The device is set to cool. | -| STATE_IDLE | The device is idle. | -| STATE_AUTO | The device is set to auto. | -| STATE_MANUAL | The device is set to manual. | -| STATE_DRY | The device is set to dry. | -| STATE_FAN_ONLY | The device is set to fan-only. | -| STATE_ECO | The device is set to eco-mode. | - -### Supported features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Name | Description | -| --------------------------------- | ------------------------------------------------------ | -| SUPPORT_TARGET_TEMPERATURE | The device supports a target temperature. | -| SUPPORT_TARGET_TEMPERATURE_HIGH | The device supports an upper bound target temperature. | -| SUPPORT_TARGET_TEMPERATURE_LOW | The device supports a lower bound target temperature. | -| SUPPORT_TARGET_HUMIDITY | The device supports a target humidity. | -| SUPPORT_TARGET_HUMIDITY_HIGH | The device supports an upper bound target humidity. | -| SUPPORT_TARGET_HUMIDITY_LOW | The device supports a lower bound target humidity. | -| SUPPORT_FAN_MODE | The device supports fan modes. | -| SUPPORT_OPERATION_MODE | The device supports operation modes. | -| SUPPORT_HOLD_MODE | The device supports hold modes. | -| SUPPORT_SWING_MODE | The device supports swing modes. | -| SUPPORT_AWAY_MODE | The device supports away mode. | -| SUPPORT_AUX_HEAT | The device supports auxiliary heaters. | -| SUPPORT_ON_OFF | The device supports on/off states. | - -## Methods - -### Set fan mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_fan_mode(self, fan_mode): - """Set new target fan mode.""" - - async def async_set_fan_mode(self, fan_mode): - """Set new target fan mode.""" -``` - -### Set hold mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_hold_mode(self, hold_mode): - """Set new target hold mode.""" - - async def async_set_hold_mode(self, hold_mode): - """Set new target hold mode.""" -``` - -### Set humidity - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_humidity(self, humidity): - """Set new target humidity.""" - - async def async_set_humidity(self, humidity): - """Set new target humidity.""" -``` - -### Set operation mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_operation_mode(self, operation_mode): - """Set new target operation mode.""" - - async def async_set_operation_mode(self, operation_mode): - """Set new target operation mode.""" -``` - -### Set swing mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_swing_mode(self, swing_mode): - """Set new target swing operation.""" - - async def async_set_swing_mode(self, swing_mode): - """Set new target swing operation.""" -``` - -### Set temperature - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_temperature(self, **kwargs): - """Set new target temperature.""" - - async def async_set_temperature(self, **kwargs): - """Set new target temperature.""" -``` - -### Turn auxiliary heater on - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_aux_heat_on(self): - """Turn auxiliary heater on.""" - - async def async_turn_aux_heat_on(self): - """Turn auxiliary heater on.""" -``` - -### Turn auxiliary heater off - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_aux_heat_off(self): - """Turn auxiliary heater off.""" - - async def async_turn_aux_heat_off(self): - """Turn auxiliary heater off.""" -``` - -### Turn away mode on - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_away_mode_on(self): - """Turn away mode on.""" - - async def async_turn_away_mode_on(self): - """Turn away mode on.""" -``` - -### Turn away mode off - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_away_mode_off(self): - """Turn away mode off.""" - - async def async_turn_away_mode_off(self): - """Turn away mode off.""" -``` - -### Turn the device on - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_on(self): - """Turn device on.""" - - async def async_turn_on(self): - """Turn device on.""" -``` - -### Turn the device off - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_off(self): - """Turn device off.""" - - async def async_turn_off(self): - """Turn device off.""" -``` \ No newline at end of file diff --git a/website/translated_docs/pl/entity_cover.md b/website/translated_docs/pl/entity_cover.md deleted file mode 100644 index 9fe8a9ce..00000000 --- a/website/translated_docs/pl/entity_cover.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: Cover Entity -sidebar_label: Cover ---- - -A cover entity is a device that controls an opening or cover, such as a garage door and window shade. Derive entity platforms from [`homeassistant.components.cover.CoverDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/cover/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -### Platform Properties (to be implemented by deriving platform classes) - -| Name | Type | Default | Description | -| ----------------------------- | ---- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | -| current_cover_position | int | None | The current position of cover where 0 means closed and 100 is fully open. Required with `SUPPORT_SET_POSITION`. | -| current_cover_tilt_position | int | None | The current tilt position of the cover where 0 means closed/no tilt and 100 means open/maximum tilt. Required with `SUPPORT_SET_TILT_POSITION` | -| is_opening | bool | None | If the cover is opening or not. Used to determine `state`. | -| is_closing | bool | None | If the cover is closing or not. Used to determine `state`. | -| is_closed | bool | `NotImplementedError()` | If the cover is closed or not. if the state is unknown, return `None`. Used to determine `state`. | - -### Entity Properties (base class properties which may be overriden) - -| Name | Type | Default | Description | -| ------------------ | ------------- | -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ | -| device_class | string | None | Describes the type/class of the cover. Must be `None` or one of the valid values from the table below. | -| supported_features | int (bitwise) | Value determined from `current_cover_position` and `current_cover_tilt_position` | Describes the supported features. See the related table below for details. | - -### Device Classes - -| Constant | Description | -| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `DEVICE_CLASS_AWNING` | Control of an awning, such as an exterior retractible window, door, or patio cover. | -| `DEVICE_CLASS_BLIND` | Control of blinds, which are linked slats that expand or collapse to cover an opening or may be tilted to partially cover an opening, such as window blinds. | -| `DEVICE_CLASS_CURTAIN` | Control of curtains or drapes, which is often fabric hung above a window or door that can be drawn open. | -| `DEVICE_CLASS_DAMPER` | Control of a mechanical damper that reduces air flow, sound, or light. | -| `DEVICE_CLASS_DOOR` | Control of a door or gate that provides access to an area. | -| `DEVICE_CLASS_GARAGE` | Control of a garage door that provides access to a garage. | -| `DEVICE_CLASS_SHADE` | Control of shades, which are a continous plane of material or connected cells that expanded or collapsed over an opening, such as window shades. | -| `DEVICE_CLASS_SHUTTER` | Control of shutters, which are linked slats that swing out/in to cover an opening or may be tilted to partially cover an opening, such as indoor or exterior window shutters. | -| `DEVICE_CLASS_WINDOW` | Control of a physical window that opens and closes or may tilt. | - -### States - -| Constant | Description | -| --------------- | --------------------------------------------------------------- | -| `STATE_OPENING` | The cover is in the process of opening to reach a set position. | -| `STATE_OPEN` | The cover has reached the open position. | -| `STATE_CLOSING` | The cover is in the process of closing to reach a set position. | -| `STATE_CLOSED` | The cover has reach the closed position. | - -### Supported Features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Constant | Description | -| --------------------------- | -------------------------------------------------------------------------------- | -| `SUPPORT_OPEN` | The cover supports being opened. | -| `SUPPORT_CLOSE` | The cover supports being closed. | -| `SUPPORT_SET_POSITION` | The cover supports moving to a specific position between opened and closed. | -| `SUPPORT_STOP` | The cover supports stopping the current action (open, close, set position) | -| `SUPPORT_OPEN_TILT` | The cover supports being tilting open. | -| `SUPPORT_CLOSE_TILT` | The cover supports being tilting closed. | -| `SUPPORT_SET_TILT_POSITION` | The cover supports moving to a specific tilt position between opened and closed. | -| `SUPPORT_STOP_TILT` | The cover supports stopping the current tilt action (open, close, set position) | - -## Methods - -### Open cover - -Only implement this method if the flag `SUPPORT_CLOSE` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover(self, **kwargs): - """Open the cover.""" - - async def async_open_cover(self, **kwargs): - """Open the cover.""" -``` - -### Close cover - -Only implement this method if the flag `SUPPORT_CLOSE` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover(self, **kwargs): - """Close cover.""" - - async def async_close_cover(self, **kwargs): - """Close cover.""" -``` - -### Set cover position - -Only implement this method if the flag `SUPPORT_SET_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" - - async def async_set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" - -``` - -### Stop cover - -Only implement this metohd if the flag `SUPPORT_STOP` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover(self, **kwargs): - """Stop the cover.""" -``` - -### Open cover tilt - -Only implement this method if the flag `SUPPORT_OPEN_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" - - async def async_open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" -``` - -### Close cover tilt - -Only implement this method if the flag `SUPPORT_CLOSE_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" - - async def async_close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" -``` - -### Set cover tilt position - -Only implement this method if the flag `SUPPORT_SET_TILT_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" - - async def async_set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" -``` - -### Stop cover tilt - -Only implement this method if the flag `SUPPORT_STOP_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover_tilt(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover_tilt(self, **kwargs): - """Stop the cover.""" -``` \ No newline at end of file diff --git a/website/translated_docs/pl/entity_fan.md b/website/translated_docs/pl/entity_fan.md deleted file mode 100644 index 27b6f7dc..00000000 --- a/website/translated_docs/pl/entity_fan.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Fan Entity -sidebar_label: Fan ---- - -A fan entity is a device that controls the different vectors of your fan such as speed, direction and oscillation. Derive enitity platforms from ['homeassistant.components.fan.FanDevice'](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/fan/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------------ | ------- | ------- | --------------------------------------- | -| current_direction | str | None | Return the current direction of the fan | -| is_on | boolean | None | Return true if the entity is on | -| speed | str | None | Return the current speed | -| speed_list | list | None | Get the list of available speeds | -| state_attributes | dict | None | Return optional state attributes | -| supported_features | int | None | Flag supported features | - -## Supported Features - -| Constant | Description | -| --------------------- | ---------------------------------------------- | -| 'SUPPORT_DIRECTION' | The fan supports changing the direction of it. | -| 'SUPPORT_SET_SPEED' | The fan supports setting the speed. | -| 'SUPPORT_OSCILLATE' | The fan supports oscillation. | - -## Methods - -### Set direction - -Only implement this method if the flag `SUPPORT_DIRECTION` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def set_direction(self, direction: str) -> None: - """Set the direction of the fan.""" - - async def async_set_direction(self, direction: str): - """Set the direction of the fan.""" -``` - -### Set speed - -Only implement this method if the flag `SUPPORT_SET_SPEED` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def set_speed(self, speed: str) -> None: - """Set the speed of the fan.""" - - async def async_set_speed(self, speed: str): - """Set the speed of the fan.""" -``` - -### Turn on - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def turn_on(self, speed: str = None, **kwargs) -> None: - """Turn on the fan.""" - - async def async_turn_on(self, speed: str = None, **kwargs): - """Turn on the fan.""" -``` - -### Oscillate - -Only implement this method if the flag `SUPPORT_OSCILLATE` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def oscillate(self, oscillating: bool) -> None: - """Oscillate the fan.""" - - def async_oscillate(self, oscillating: bool): - """Oscillate the fan.""" -``` \ No newline at end of file diff --git a/website/translated_docs/pl/entity_index.md b/website/translated_docs/pl/entity_index.md deleted file mode 100644 index 5385e078..00000000 --- a/website/translated_docs/pl/entity_index.md +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Entity -sidebar_label: Introduction ---- - -Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating. - -Below is an example switch entity that keeps track of their state in memory. - -```python -from homeassistant.components.switch import SwitchDevice - -class MySwitch(SwitchDevice): - - def __init__(self): - self._is_on = False - - @property - def name(self): - """Name of the device.""" - return 'My Switch' - - @property - def is_on(self): - """If the switch is currently on or off.""" - return self._is_on - - def turn_on(self, **kwargs): - """Turn the switch on.""" - self._is_on = True - - def turn_off(self, **kwargs): - """Turn the switch off.""" - self._is_on = False -``` - -That's all there is to it to build a switch entity! Continue reading to learn more or check out the [video tutorial](https://youtu.be/Cfasc9EgbMU?t=737). - -## Updating the entity - -An entity represents a device. There are various strategies to keep your entity in sync with the state of the device, the most popular one being polling. - -### Polling - -With polling, Home Assistant will ask the entity from time to time (depending on the update interval of the component) to fetch the latest state. Home Assistant will poll an entity when the `should_poll` property returns `True` (the default value). You can either implement your update logic using `update()` or the async method `async_update()`. This method should fetch the latest state from the device and store it in an instance variable for the properties to return it. - -### Subscribing to updates - -When you subscribe to updates, your code is responsible for letting Home Assistant know that an update is available. Make sure you have the `should_poll` property return `False`. - -Whenever you receive new state from your subscription, you can tell Home Assistant that an update is available by calling `schedule_update_ha_state()` or async callback `async_schedule_update_ha_state()`. Pass in the boolean `True` to the method if you want Home Assistant to call your update method before writing the update to Home Assistant. - -## Generic properties - -The entity base class has a few properties that are common among all entities in Home Assistant. These can be added to any entity regardless of the type. All these properties are optional and don't need to be implemented. - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| assumed_state | boolean | `False` | Return `True` if the state is based on our assumption instead of reading it from the device. | -| available | boolean | `True` | Indicate if Home Assistant is able to read the state and control the underlying device. | -| device_state_attributes | dict | `None` | Extra information to store in the state machine. It needs to be information that further explains the state, it should not be static information like firmware version. See [below](entity_index.md#standard_attributes) for details of standard attributes. | -| entity_picture | URL | `None` | Url of a picture to show for the entity. | -| name | string | `None` | Name of the entity | -| should_poll | boolean | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](#methods). | -| unique_id | string | `None` | A unique identifier for this entity. Needs to be unique within a platform (ie `light.hue`). Should not be configurable by the user or be changeable. [Learn more.](entity_registry_index.md#unique-id-requirements) | - -## Advanced properties - -The following properties are also available on entities. However, they are for advanced use only and should be used with caution. - -| Name | Type | Default | Description | -| ------------ | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| force_update | boolean | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine. | -| hidden | boolean | `False` | Indicate if the entity should not be shown on the frontend. | -| icon | icon | `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all devices. | - -## Standard attributes - -The following `device_state_attributes` are considered standard and should follow the convention below. The constant should be imported from `homeassistant/const.py`. - -| Name | Type | Unit | Constant | Description | -| ---------------- | ------- | ---- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| battery_charging | boolean | N/A | `ATTR_BATTERY_CHARGING` | Battery charging status of the entity, shown as a boolean `true` or `false`. If charging is not supported, then this attribute should not be created. | -| battery_level | integer | % | `ATTR_BATTERY_LEVEL` | Battery level of the entity, shown as an integer percentage between 0-100. | - -## Lifecycle hooks - -Use these lifecycle hooks to execute code when certain events happen to the entity. All lifecycle hooks are async methods. - -### `async_added_to_hass()` - -Called when an entity has their entity_id and hass object assigned, before it is written to the state machine for the first time. Example uses: restore the state, subscribe to updates or set callback/dispatch function/listener. - -### `async_will_remove_from_hass()` - -Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates. - -## Changing the entity model - -If you want to add a new feature to an entity or any of its subtypes (light, switch, etc), you will need to propose it first in our [architecture repo](https://github.com/home-assistant/architecture/issues). Only additions will be considered that are common features among various vendors. \ No newline at end of file diff --git a/website/translated_docs/pl/entity_light.md b/website/translated_docs/pl/entity_light.md deleted file mode 100644 index 1b3d6561..00000000 --- a/website/translated_docs/pl/entity_light.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Light Entity -sidebar_label: Light ---- - - -A light entity is a device that controls the brightness, RGB value,color temperature and effects of a light source. - -## Properties - -| Name | Type | Default | Description | -| ------------------ | ------ | ------- | --------------------------------------------------------- | -| brightness | int | None | Return the brightness of this light between 0..255 | -| color_temp | int | None | Return the CT color value in mireds. | -| effect | String | None | Return the current effect. | -| effect_list | list | None | Return the list of supported effects. | -| hs_color | list | None | Return the hue and saturation color value [float, float]. | -| is_on | bool | bool | Returns if the light entity is on or not. | -| max_minreds | int | int | Return the warmest color_temp that this light supports. | -| min_mireds | int | int | Return the coldest color_temp that this light supports. | -| supported_features | int | int | Flag supported features. | -| white_value | int | None | Return the white value of this light between 0..255. | - -## Support Feature - -| Constant | Description | -| --------------------- | --------------------------------------------------------------------- | -| `SUPPORT_BRIGHTNESS` | Controls the brightness of a light source | -| `SUPPORT_COLOR` | Controls the color a light source shows | -| `SUPPORT_COLOR_TEMP` | Controls the representation a light source shows based on temperature | -| `SUPPORT_EFFECT` | Controls the effect a light source shows | -| `SUPPORT_FLASH` | Controls the duration of a flash a light source shows | -| `SUPPORT_TRANSITION` | Controls the duration of transitions between color and effects | -| `SUPPORT_WHITE_VALUE` | Controls the white light a light source shows. | - -## Methods - -# Turn on Light Device - -```python -class MyLightDevice(LightDevice): - def turn_on(self, **kwargs): - """Turn the device on.""" - - async def async_turn_on(self, **kwargs): - """Turn device on.""" - -``` - -# Turn Off Light Device - -```python -class MyLightDevice(LightDevice): - - def turn_off(self, **kwargs): - """Turn the device off.""" - - async def async_turn_off(self, **kwargs): - """Turn device off.""" - -``` \ No newline at end of file diff --git a/website/translated_docs/pl/entity_lock.md b/website/translated_docs/pl/entity_lock.md deleted file mode 100644 index 7983db21..00000000 --- a/website/translated_docs/pl/entity_lock.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Lock Entity -sidebar_label: Lock ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ---- | ---- | ------- | ----------- | -| | | | | - -## Methods \ No newline at end of file diff --git a/website/translated_docs/pl/entity_media_player.md b/website/translated_docs/pl/entity_media_player.md deleted file mode 100644 index ab327f05..00000000 --- a/website/translated_docs/pl/entity_media_player.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Media Player Entity -sidebar_label: Media Player ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| --------------------------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------- | -| sound_mode | string | None | The current sound mode of the media player | -| sound_mode_list | list | None | Dynamic list of available sound modes (set by platform, empty means sound mode not supported) | -| source | string | None | The currently selected input source for the media player. | -| source_list | list | None | The list of possible input sources for the media player. (This list should contain human readable names, suitible for frontend display) | -| media_image_url | string | None | URL that represents the current image. | -| media_image_remotely_accessible | boolean | False | Return `True` if property `media_image_url` is accessible outside of the home network. | -| device_class | string | `None` | Type of binary sensor. | - -## Methods - -### Select sound mode - -Optional. Switch the sound mode of the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - def async_select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - -### Select source - -Optional. Switch the selected input source for the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_source(self, source): - """Select input source.""" - - def async_select_source(self, source): - """Select input source.""" - - -### Mediatype - -Required. Returns one of the defined constants from the below list that matches the mediatype - -| CONST | -| --------------------- | -| MEDIA_TYPE_MUSIC | -| MEDIA_TYPE_TVSHOW | -| MEDIA_TYPE_MOVIE | -| MEDIA_TYPE_VIDEO | -| MEDIA_TYPE_EPISODE | -| MEDIA_TYPE_CHANNEL | -| MEDIA_TYPE_PLAYLIST | -| MEDIA_TYPE_IMAGE | -| MEDIA_TYPE_URL | -| MEDIA_TYPE_GAME | -| MEDIA_TYPE_APP | - - class MyMediaPlayer(MediaPlayerDevice): - # Implement the following method. - - def media_content_type(self): - """Content type of current playing media.""" - - -### Available device classes - -Optional. What type of media device is this. It will possibly map to google device types. - -| Value | Description | -| ------- | ----------------------------------------- | -| tv | Device is a television type device. | -| speaker | Device is speakers or stereo type device. | \ No newline at end of file diff --git a/website/translated_docs/pl/entity_registry_index.md b/website/translated_docs/pl/entity_registry_index.md deleted file mode 100644 index aa346829..00000000 --- a/website/translated_docs/pl/entity_registry_index.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -title: Entity Registry -sidebar_label: Introduction ---- - -The entity registry is a registry where Home Assistant keeps track of entities. Any entity that is added to Home Assistant and has a unique ID will be registered in the registry. - -Being registered has the advantage that the same entity will always get the same entity ID. It will also prevent other entities from using that entity ID. - -A user is also able to override the name of an entity in the entity registry. When set, the name of the entity registry is used in favor of the name the device might give itself. - -## Unique ID requirements - -An entity is looked up in the registry based on a combination of the plaform type (e.g., `light`), and the integration name (domain) (ie hue) and the unique ID of the entity. It is therefore very important that the unique ID is unique! It is also important that it is not possible for the user to change the unique ID, because that means it will lose all its settings related to it. - -Good sources for a unique ID: - -- Serial number of a device -- MAC address of a device -- latitude/longitude - -If a device has a single serial but provides multiple entities, combine the serial with unique identifiers for the entities. For example, if a device measures both temperature and humidity, you can uniquely identify the entities using `{serial}-{sensor_type}`. \ No newline at end of file diff --git a/website/translated_docs/pl/entity_remote.md b/website/translated_docs/pl/entity_remote.md deleted file mode 100644 index b4a0251d..00000000 --- a/website/translated_docs/pl/entity_remote.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Remote Entity -sidebar_label: Remote ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ---- | ---- | ------- | ----------- | -| | | | | - -## Methods \ No newline at end of file diff --git a/website/translated_docs/pl/entity_sensor.md b/website/translated_docs/pl/entity_sensor.md deleted file mode 100644 index 6a7e6307..00000000 --- a/website/translated_docs/pl/entity_sensor.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Sensor Entity -sidebar_label: Sensor ---- - -A sensor is a read-only entity that provides some information. Information has a value and optionally, a unit of measurement. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| --------------------- | ------ | ------------ | -------------------------------------------------------- | -| state | string | **Required** | The value of the sensor. | -| unit_of_measurement | string | `None` | The unit of measurement that the sensor is expressed in. | -| device_class | string | `None` | Type of sensor. | - -### Available device classes - -If specifying a device class, your sensor entity will need to also return the correct unit of measurement. - -| Type | Unit | Description | -| --------------- | -------- | -------------------------- | -| battery | % | % of battery that is left. | -| humidity | % | % of humidity in the air. | -| illuminance | lx/lm | Light level. | -| signal_strength | dB/dBm | Signal strength. | -| temperature | °C/°F | Temperature. | -| timestamp | ISO8601 | Timestamp. | -| power | W,kW | Power. | -| pressure | hPa,mbar | Pressure. | \ No newline at end of file diff --git a/website/translated_docs/pl/entity_switch.md b/website/translated_docs/pl/entity_switch.md deleted file mode 100644 index 14039422..00000000 --- a/website/translated_docs/pl/entity_switch.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Switch Entity -sidebar_label: Switch ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------------ | ------- | ------------ | ----------------------------------------------------------------------- | -| is_on | boolean | **Required** | If the switch is currently on or off. | -| current_power_w | float | `None` | The current power usage in W. | -| today_energy_kwh | float | `None` | Total energy usage in kWh. | -| is_standby | boolean | `None` | Indicate if the device connected to the switch is currently in standby. | - -## Methods - -### Turn On - -Turn the switch on. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def turn_on(self, **kwargs) -> None: - """Turn the entity on.""" - - async def async_turn_on(self, **kwargs): - """Turn the entity on.""" - -``` - -### Turn Off - -Turn the switch off. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def turn_off(self, **kwargs): - """Turn the entity off.""" - - async def async_turn_off(self, **kwargs): - """Turn the entity off.""" -``` - -### Toggle - -Optional. If not implemented will default to checking what method to call using the `is_on` property. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def toggle(self, **kwargs): - """Toggle the entity.""" - - async def async_toggle(self, **kwargs): - """Toggle the entity.""" -``` - -### Available device classes - -Optional. What type of device this. It will possibly map to google device types. - -| Value | Description | -| ------ | ----------------------------------------- | -| outlet | Device is an outlet for power. | -| switch | Device is switch for some type of entity. | \ No newline at end of file diff --git a/website/translated_docs/pl/entity_vacuum.md b/website/translated_docs/pl/entity_vacuum.md deleted file mode 100644 index b947d3df..00000000 --- a/website/translated_docs/pl/entity_vacuum.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Vacuum Entity -sidebar_label: Vacuum ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| -------------------- | ------ | ------------------------------- | --------------------------------------------------- | -| name | string | **Required** | Name of the device. | -| state | string | **Required** | One of the states listed in the states section. | -| battery_level | int | `none` | Current battery level. | -| battery_icon | string | function | Battery icon to show in UI. | -| cleaning_mode | string | `none` | The current cleaning mode. | -| cleaning_mode_list | list | `NotImplementedError()` | List of available fan speeds and cleaning modes. | -| error | string | **Required** with `STATE_ERROR` | An error message if the vacuum is in `STATE_ERROR`. | - -## States - -| State | Description | -| ----------------- | ------------------------------------------------------------------------------------------------------- | -| `STATE_CLEANING` | The vacuum is currently cleaning. | -| `STATE_DOCKED` | The vacuum is currently docked, it is assumed that docked can also mean charging. | -| `STATE_PAUSED` | The vacuum was cleaning but was paused without returning to the dock. | -| `STATE_IDLE` | The vacuum is not paused, not docked and does not have any errors. | -| `STATE_RETURNING` | The vacuum is done cleaning and is currently returning to the dock, but not yet docked. | -| `STATE_ERROR` | The vacuum encountered an error while cleaning, the error can be specified as a property on the entity. | - -## Methods - -### `turn_on` or `async_turn_on` - -Turn the vacuum on and start cleaning. - -### `turn_off`or `async_turn_off` - -Turn the vacuum off stopping the cleaning and returning home. - -### `return_to_base` or `async_return_to_base` - -Set the vacuum cleaner to return to the dock. - -### `stop` or `async_stop` - -Stop the vacuum cleaner, do not return to base. - -### `clean_spot` or `async_clean_spot` - -Perform a spot clean-up. - -### `locate` or `async_locate` - -Locate the vacuum cleaner. - -### `set_cleaning_mode` or `async_set_cleaning_mode` - -Set the cleaning mode. - -### `send_command` or `async_send_command` - -Send a command to a vacuum cleaner. \ No newline at end of file diff --git a/website/translated_docs/pl/entity_water_heater.md b/website/translated_docs/pl/entity_water_heater.md deleted file mode 100644 index b4a13e29..00000000 --- a/website/translated_docs/pl/entity_water_heater.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: Water Heater Entity -sidebar_label: Water Heater ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| -------------- | ------ | ------- | ------------------------------------------ | -| min_temp | float | 110°F | The minimum temperature that can be set. | -| max_temp | float | 140°F | The maximum temperature that can be set. | -| temperature | float | none | The current temperature in °C or °F. | -| operation_mode | string | none | The current operation mode. | -| operation_list | list | none | List of possible operation modes. | -| away_mode | string | none | The current status of away mode. (on, off) | - -The allowed operation modes are specified in the base component and implementations of the water_heater component cannot differ. - -Properties have to follow the units defined in the `unit_system`. - -## States - -| State | Description | -| ------------------- | ---------------------------------------------------------------- | -| `STATE_ECO` | Energy efficient mode, provides energy savings and fast heating. | -| `STATE_ELECTRIC` | Electric only mode, uses the most energy. | -| `STATE_PERFORMANCE` | High performance mode. | -| `STATE_HIGH_DEMAND` | Meet high demands when water heater is undersized. | -| `STATE_HEAT_PUMP` | Slowest to heat, but uses less energy. | -| `STATE_GAS` | Gas only mode, uses the most energy. | -| `STATE_OFF` | The water heater is off. | - -## Methods - -### `set_temperature` or `async_set_temperature` - -Sets the temperature the water heater should heat water to. - -### `set_operation_mode`or `async_set_operation_mode` - -Sets the operation mode of the water heater. Must be in the operation_list. - -### `turn_away_mode_on` or `async_turn_away_mode_on` - -Set the water heater to away mode. - -### `turn_away_mode_off` or `async_turn_away_mode_off` - -Set the water heater back to the previous operation mode. Turn off away mode. \ No newline at end of file diff --git a/website/translated_docs/pl/entity_weather.md b/website/translated_docs/pl/entity_weather.md deleted file mode 100644 index b92ccbe6..00000000 --- a/website/translated_docs/pl/entity_weather.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Weather Entity -sidebar_label: Weather ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ------------ | ------ | ------------ | ----------------------------------------------- | -| state | string | **Required** | The current weather condition. | -| temperature | float | **Required** | The current temperature in °C or °F. | -| pressure | float | `None` | The current air pressure in hPa or inHg. | -| humidity | float | `None` | The current humidity in %. | -| visibility | float | `None` | The current visibility in km or mi. | -| wind_speed | float | `None` | The current wind speed in km/h or mi/h. | -| wind_bearing | string | `None` | The current wind bearing, 1-3 letters. | -| forecast | array | `None` | Daily or Hourly forecast data. | -| attribution | string | `None` | The branding text required by the API provider. | - -Properties have to follow the units defined in the `unit_system`. - -### Forecast - -Forecast data should either be daily or hourly. - -| Name | Type | Default | Description | -| ----------- | ------ | ------------ | --------------------------------------- | -| datetime | string | **Required** | UTC Date time in RFC 3339 format. | -| temperature | float | **Required** | The higher temperature in °C or °F | -| condition | string | `None` | The weather condition at this point. | -| templow | float | `None` | The lower daily Temperature in °C or °F | - -### Recommended values for state and condition - -These weather conditions are included in our translation files and also show the corresponding icon. - -| Condition | Description | -| --------------- | --------------------------------- | -| clear-night | Clear night | -| cloudy | Many clouds | -| fog | Fog | -| lightning | Lightning/ thunderstorms | -| lightning-rainy | Lightning/ thunderstorms and rain | -| partlycloudy | A few clouds | -| pouring | Pouring rain | -| rainy | Rain | -| snowy | Snow | -| snowy-rainy | Snow and Rain | -| sunny | Sunshine | -| windy | Wind | -| windy-variant | Wind and clouds | - -This means that the `weather` platforms don't need to support languages. \ No newline at end of file diff --git a/website/translated_docs/pl/external_api_rest.md b/website/translated_docs/pl/external_api_rest.md deleted file mode 100644 index 965aae96..00000000 --- a/website/translated_docs/pl/external_api_rest.md +++ /dev/null @@ -1,530 +0,0 @@ ---- -title: "REST API" ---- - -Home Assistant provides a RESTful API on the same port as the web frontend. (default port is port 8123). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -- http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -- http://IP_ADDRESS:8123/api/ is a RESTful API. - -The API accepts and returns only JSON encoded objects. - -All API calls have to be accompanied by the header `Authorization: Bearer ABCDEFGH`, where `ABCDEFGH` is replaced by your token. You can obtain a token ("Long-Lived Access Token") by logging into the frontend using a web browser, and going to [your profile](https://www.home-assistant.io/docs/authentication/#your-account-profile) `http://IP_ADDRESS:8123/profile`. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```bash -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. - -```python -from requests import get - -url = 'http://localhost:8123/ENDPOINT' -headers = { - 'Authorization': 'Bearer ABCDEFGH', - 'content-type': 'application/json', -} - -response = get(url, headers=headers) -print(response.text) -``` - -Another option is to use the Restful Command component https://www.home-assistant.io/components/rest_command/ in a Home Assistant automation or script. - -```yaml -turn_light_on: - url: http://localhost:8123/api/states/light.study_light - method: POST - headers: - authorization: 'Bearer ABCDEFGH' - content-type: 'application/json' - payload: '{"state":"on"}' -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on one or more entities - comma separated. -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates the current state of an entity. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance. - - -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` \ No newline at end of file diff --git a/website/translated_docs/pl/external_api_rest_python.md b/website/translated_docs/pl/external_api_rest_python.md deleted file mode 100644 index 3d415b76..00000000 --- a/website/translated_docs/pl/external_api_rest_python.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: "REST API - Python bindings" ---- - -This API is deprecated and was removed since Home Assistant 0.77.0 - -More information can be found in this [blog post](../../../blog/2018/08/13/deprecating-remote-package.html). \ No newline at end of file diff --git a/website/translated_docs/pl/external_api_server_sent_events.md b/website/translated_docs/pl/external_api_server_sent_events.md deleted file mode 100644 index 676494c3..00000000 --- a/website/translated_docs/pl/external_api_server_sent_events.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: "Server-sent events" ---- - -The [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) feature is a one-way channel from your Home Assistant server to a client which is acting as a consumer. For a bi-directional streaming API, check out the [WebSocket API](external_api_websocket.md). - -The URI that is generating the data is `/api/stream`. - -A requirement on the client-side is existing support for the [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) interface. - -There are various ways to access the stream. If you have not set an `api_password` in the [`http`](https://www.home-assistant.io/components/http/) section of your `configuration.yaml` file then you use your modern browser to read the messages. A command-line option is `curl`: - -```bash -$ curl -X GET -H 'Authorization: Bearer ABCDEFGH' \ - -H "Content-Type: application/json" http://localhost:8123/api/stream -``` - -> Will no longer work with the new Authentication system. - -You can create a convenient view for this by creating an HTML file (`sse.html`) in the `www` folder of your Home Assistant configuration directory (`.homeassistant`). Paste this snippet into the file: - -```html - - - -

Getting Home Assistant server events

-
- - - -``` - -Visit to see the stream of events. - -## Examples - -A simple way to consume server-sent events is to use a command-line http client like [httpie](https://httpie.org/). Installation info is on the site (if you use Homebrew, it's `brew install httpie`). Once installed, run this snippet from your terminal: - -```bash -$ http --stream http://localhost:8123/api/stream 'Authorization:Bearer ABCDEFGH' content-type:application/json -``` - -### Website - -> Will no longer work with the new Authentication system. - -The [home-assistant-sse](https://github.com/fabaff/home-assistant-sse) repository contains a more advanced example. - -### Python - -If you want to test the server-sent events without creating a website, the Python module [`sseclient` ](https://pypi.python.org/pypi/sseclient/) can help. To install (assuming Python and pip3 are already installed): - -```bash -$ pip3 install sseclient -``` - -A simple script to consume SSE in Python looks like this: - -```python -from sseclient import SSEClient - -auth = {'Authorization': 'Bearer ABCDEFGH'} -messages = SSEClient('http://localhost:8123/api/stream', headers=auth) - -for msg in messages: - print(msg) -``` \ No newline at end of file diff --git a/website/translated_docs/pl/external_api_websocket.md b/website/translated_docs/pl/external_api_websocket.md deleted file mode 100644 index f194c309..00000000 --- a/website/translated_docs/pl/external_api_websocket.md +++ /dev/null @@ -1,434 +0,0 @@ ---- -title: "WebSocket API" ---- - -Home Assistant contains a WebSocket API. This API can be used to stream information from a Home Assistant instance to any client that implements WebSockets. Implementations in different languages: - -- [JavaScript](https://github.com/home-assistant/home-assistant-js-websocket) - powers the frontend -- [Python](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket-client.py) - CLI client using [`asyncws`](https://async-websockets.readthedocs.io/en/latest/) -- [JavaScript/HTML](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket.html) - WebSocket connection in your browser - -Connect your websocket implementation to `ws://localhost:8123/api/websocket`. You will need a valid access token. - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`websocket_api` component](https://www.home-assistant.io/components/websocket_api/) to your `configuration.yaml` file to use the WebSocket API. - -## Server states - -1. Client connects. -2. Authentication phase starts. - - Server sends `auth_required` message. - - Client sends `auth` message. - - If `auth` message correct: go to 3. - - Server sends `auth_invalid`. Go to 6. -3. Send `auth_ok` message -4. Authentication phase ends. -5. Command phase starts. - 1. Client can send commands. - 2. Server can send results of previous commands. -6. Client or server disconnects session. - -During the command phase, the client attaches a unique identifier to each message. The server will add this identifier to each message so that the client can link each message to its origin. - -## Message format - -Each API message is a JSON serialized object containing a `type` key. After the authentication phase messages also must contain an `id`, an integer that contains the number of interactions. - -Example of an auth message: - -```json -{ - "type": "auth", - "access_token": "ABCDEFGHIJKLMNOPQ" -} -``` - -```json -{ - "id": 5, - "type":"event", - "event":{ - "data":{}, - "event_type":"test_event", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -## Authentication phase - -When a client connects to the server, the server will test if the client is authenticated. Authentication will not be necessary if no api_password is set or if the user fulfills one of the other criteria for authentication (trusted network, password in url/header). - -If no authentication is needed, the authentication phase will complete and the server will send an `auth_ok` message. - -```json -{ - "type": "auth_ok" -} -``` - -If authentication is necessary, the server sends out `auth_required`. - -```json -{ - "type": "auth_required" -} -``` - -This means that the next message from the client should be an auth message. You can authorize with an access token. - -```json -{ - "type": "auth", - "access_token": "ABCDEFGH" -} -``` - -For now, we also support authentication with an API password (legacy auth). - -```json -{ - "type": "auth", - "api_password": "supersecret" -} -``` - -If the client supplies valid authentication, the authentication phase will complete by the server sending the `auth_ok` message: - -```json -{ - "type": "auth_ok" -} -``` - -If the data is incorrect, the server will reply with `auth_invalid` message and disconnect the session. - -```json -{ - "type": "auth_invalid", - "message": "Invalid password" -} -``` - -## Command phase - -During this phase the client can give commands to the server. The server will respond to each command with a `result` message indicating when the command is done and if it was successful. - -```json -{ - "id": 6, - "type": "result", - "success": true, - // Can contain extra result info - "result": null -} -``` - -## Subscribe to events - -The command `subscribe_events` will subscribe your client to the event bus. You can either listen to all events or to a specific event type. If you want to listen to multiple event types, you will have to send multiple `subscribe_events` commands. - -```json -{ - "id": 18, - "type": "subscribe_events", - // Optional - "event_type": "state_changed" -} -``` - -The server will respond with a result message to indicate that the subscription is active. - -```json -{ - "id": 18, - "type": "result", - "success": true, - "result": null -} -``` - -For each event that matches, the server will send a message of type `event`. The `id` in the message will point at the original `id` of the `listen_event` command. - -```json -{ - "id": 18, - "type":"event", - "event":{ - "data":{ - "entity_id":"light.bed_light", - "new_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:24.265390+00:00", - "state":"on", - "attributes":{ - "rgb_color":[ - 254, - 208, - 0 - ], - "color_temp":380, - "supported_features":147, - "xy_color":[ - 0.5, - 0.5 - ], - "brightness":180, - "white_value":200, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:24.265390+00:00" - }, - "old_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:10.466994+00:00", - "state":"off", - "attributes":{ - "supported_features":147, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:10.466994+00:00" - } - }, - "event_type":"state_changed", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -### Unsubscribing from events - -You can unsubscribe from previously created subscription events. Pass the id of the original subscription command as value to the subscription field. - -```json -{ - "id": 19, - "type": "unsubscribe_events", - "subscription": 18 -} -``` - -The server will respond with a result message to indicate that unsubscribing was successful. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": null -} -``` - -## Calling a service - -This will call a service in Home Assistant. Right now there is no return value. The client can listen to `state_changed` events if it is interested in changed entities as a result of a service call. - -```json -{ - "id": 24, - "type": "call_service", - "domain": "light", - "service": "turn_on", - // Optional - "service_data": { - "entity_id": "light.kitchen" - } -} -``` - -The server will indicate with a message indicating that the service is done executing. - -```json -{ - "id": 24, - "type": "result", - "success": true, - "result": null -} -``` - -## Fetching states - -This will get a dump of all the current states in Home Assistant. - -```json -{ - "id": 19, - "type": "get_states" -} -``` - -The server will respond with a result message containing the states. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -## Fetching config - -This will get a dump of the current config in Home Assistant. - -```json -{ - "id": 19, - "type": "get_config" -} -``` - -The server will respond with a result message containing the config. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -## Fetching services - -This will get a dump of the current services in Home Assistant. - -```json -{ - "id": 19, - "type": "get_services" -} -``` - -The server will respond with a result message containing the services. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -## Fetching panels - -This will get a dump of the current registered panels in Home Assistant. - -```json -{ - "id": 19, - "type": "get_panels" -} -``` - -The server will respond with a result message containing the current registered panels. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -## Fetching camera thumbnails - -*Introduced in Home Assistant 0.69.* - -Return a b64 encoded thumbnail of a camera entity. - -```json -{ - "id": 19, - "type": "camera_thumbnail" -} -``` - -The server will respond with a result message containing the thumbnail. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Fetching media player thumbnails - -*Introduced in Home Assistant 0.69.* - -Fetch a base64 encoded thumbnail picture for a media player. - -```json -{ - "id": 19, - "type": "media_player_thumbnail", - "entity_id": "media_player.living_room" -} -``` - -The server will respond with the image encoded via base64. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Pings and Pongs - -The API supports receiving a ping from the client and returning a pong. This serves as a heartbeat to ensure the connection is still alive: - -```json -{ - "id": 19, - "type": "ping" -} -``` - -The server must send a pong back as quickly as possible, if the connection is still active: - -```json -{ - "id": 19, - "type": "pong" -} -``` - -## Error handling - -If an error occurs, the `success` key in the `result` message will be set to `false`. It will contain an `error` key containing an object with two keys: `code` and `message`. - -| Code | Description | -| ---- | ------------------------------------------------------------------------- | -| 1 | A non-increasing identifier has been supplied. | -| 2 | Received message is not in expected format (voluptuous validation error). | -| 3 | Requested item cannot be found | - -```json -{ - "id": 12, - "type":"result", - "success": false, - "error": { - "code": 2, - "message": "Message incorrectly formatted: expected str for dictionary value @ data['event_type']. Got 100" - } -} -``` \ No newline at end of file diff --git a/website/translated_docs/pl/frontend_add_card.md b/website/translated_docs/pl/frontend_add_card.md deleted file mode 100644 index 5958da27..00000000 --- a/website/translated_docs/pl/frontend_add_card.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: "Adding state card" ---- - -The main interface of Home Assistant is a list of the current entities and their states. For each entity in the system, a state card will be rendered. State cards will show an icon, the name of the entity, when the state has last changed and the current state or a control to interact with it. - -![Cards in the frontend](/img/en/frontend/frontend-cards1.png) - -The different card types can be found [here](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary). - -Sensors, when not grouped, are shown as so-called badges on top of the state cards. - -![Badges in the frontend](/img/en/frontend/frontend-badges.png) - -The different badges are located in the file [`/src/components/entity/ha-state-label-badge.js`](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/components/entity/ha-state-label-badge.js). - -Adding a custom card type can be done with a few simple steps. For this example we will add a new state card for the domain `camera`: - -1. Add `'camera'` to the array `DOMAINS_WITH_CARD` in the file [/common/const.ts](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/common/const.ts). -2. Create the files `state-card-camera.js` in the folder [/state-summary/](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary). -3. Add `import './state-card-camera.js';` to [state-card-content.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/state-summary/state-card-content.js). \ No newline at end of file diff --git a/website/versioned_docs/version-0.100.0/creating_component_index.md b/website/versioned_docs/version-0.100.0/creating_component_index.md deleted file mode 100644 index b15a2ce6..00000000 --- a/website/versioned_docs/version-0.100.0/creating_component_index.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Creating your first integration -id: version-0.100.0-creating_component_index -original_id: creating_component_index ---- - -Alright, you learned about the [manifest](creating_integration_manifest.md), so it's time to write your first code for your integration. AWESOME. Don't worry, we've tried hard to keep it as easy as possible. From a Home Assistant development environment, type the following and follow the instructions: - -```python -python3 -m script.scaffold integration -``` - -This will set you up with everything that you need to build an integration that is able to be set up via the user interface. More extensive examples of integrations are available from [our example repository](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/). - -## The minimum - -The scaffold integration contains a bit more than just the bare minimum. The minimum is that you define a `DOMAIN` constant that contains the domain of the integration. The second part is that it needs to define a setup method that returns a boolean if the set up was successful. - -```python -DOMAIN = 'hello_state' - -def setup(hass, config): - hass.states.set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -And if you prefer an async component: - -```python -DOMAIN = 'hello_state' - -async def async_setup(hass, config): - hass.states.async_set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -To load this, add `hello_state:` to your `configuration.yaml` file and create a file `/custom_components/hello_state/__init__.py` with one of the two codeblocks above to test it locally. - -## What the scaffold offers - -When using the scaffold script, it will go past the bare minimum of an integration. It will include a config flow, tests for the config flow and basic translation infrastructure to provide internationalization for your config flow. diff --git a/website/versioned_docs/version-0.100.0/creating_platform_code_review.md b/website/versioned_docs/version-0.100.0/creating_platform_code_review.md deleted file mode 100644 index 7a10356b..00000000 --- a/website/versioned_docs/version-0.100.0/creating_platform_code_review.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Checklist for creating a platform -sidebar_label: Platform Checklist -id: version-0.100.0-creating_platform_code_review -original_id: creating_platform_code_review ---- - -A checklist of things to do when you're adding a new platform. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on platform level - * Use `CONF_MONITORED_CONDITIONS` instead of `CONF_MONITORED_VARIABLES` - -### 1. Requirements - - 1. Requirements have been added to [`manifest.json`](creating_integration_manifest.md). The `REQUIREMENTS` constant is deprecated. - 2. Requirement version should be pinned: `"requirements": ['phue==0.8.1']` - 3. We no longer want requirements hosted on GitHub. Please upload to PyPi. - -### 2. Configuration - - 1. If the platform can be set up directly, add a voluptuous schema for [configuration validation](development_validation.md) - 2. Voluptuous schema extends schema from component
(e.g., `hue.light.PLATFORM_SCHEMA` extends `light.PLATFORM_SCHEMA`) - 3. Default parameters specified in voluptuous schema, not in `setup_platform(...)` - 4. Your `PLATFORM_SCHEMA` should use as many generic config keys as possible from `homeassistant.const` - 5. Never depend on users adding things to `customize` to configure behavior inside your platform. - -```python -import voluptuous as vol - -from homeassistant.const import CONF_FILENAME, CONF_HOST -from homeassistant.components.light import PLATFORM_SCHEMA -import homeassistant.helpers.config_validation as cv - -CONF_ALLOW_UNREACHABLE = 'allow_unreachable' -DEFAULT_UNREACHABLE = False - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_ALLOW_UNREACHABLE, - default=DEFAULT_UNREACHABLE): cv.boolean, - vol.Optional(CONF_FILENAME): cv.string, -}) -``` - -### 3. Setup Platform - - 1. Verify that the passed in configuration (user/pass/host etc.) works. - 2. Group your calls to `add_devices` if possible. - 3. If the platform adds extra services, the format should be `.`. So if your integration's domain is "awesome_sauce" and you are making a light platform, you would register services under the `awesome_sauce` domain. Make sure that your services [verify permissions](auth_permissions.md#checking-permissions). - -### 4. Entity - - 1. Extend the entity from the integration you're building a platform for. - - ```python - from homeassistant.components.light import Light - - class HueLight(Light): - ... - ``` - - 2. Avoid passing in `hass` as a parameter to the entity. When the entity has been added to Home Assistant, `hass` will be set on the entity when the entity is added to Home Assistant. This means you can access `hass` as `self.hass` inside the entity. - 3. Do not call `update()` in constructor, use `add_entities(devices, True)` instead. - 4. Do not do any I/O inside properties. Cache values inside `update()` instead. - 5. When dealing with time, state and/or attributes should not contain relative time since something happened. Instead, it should store UTC timestamps. - 6. Leverage the [entity lifecycle callbacks](entity_index.md#lifecycle-hooks) to attach event listeners or clean up connections. - -### 5. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - - ```python - # bad - status = requests.get(url('/status')) - - # good - from phue import Bridge - bridge = Bridge(...) - status = bridge.status() - ``` - - [Tutorial on publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) diff --git a/website/versioned_docs/version-0.100.0/development_environment.md b/website/versioned_docs/version-0.100.0/development_environment.md deleted file mode 100644 index f94949cb..00000000 --- a/website/versioned_docs/version-0.100.0/development_environment.md +++ /dev/null @@ -1,149 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.100.0-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev pkg-config -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example CentOS would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Due to Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run - -```bash -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is set up, perform install as for Linux. - -```bash -$ sudo apt-get update -$ sudo apt-get install python3-pip python3-dev python3-venv -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```bash -$ mkdir -p ../config -$ hass -c ../config -``` - -### Developing on macOS - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 autoconf -``` - -Then install ffmpeg: - -```bash -$ brew install ffmpeg -``` - -### Developing with devcontainer - -The devcontainer is a preconfigured development environment with all the tools you need. - -**Prerequisites** - -- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) -- [Docker](https://docs.docker.com/install/) -- [Visual Studio code](https://code.visualstudio.com/) -- [Remote - Containers (VSC Extension)](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) - -[More info about requirements and devcontainer in general](https://code.visualstudio.com/docs/remote/containers#_getting-started) - -**Getting started:** - -1. Fork the repository. -1. Clone the repository to your computer. -1. Open the repository using Visual Studio code. - -When you open this repository with Visual Studio code you are asked to "Reopen in Container", this will start the build of the container. - -_If you don't see this notification, open the command pallet and select `Remote-Containers: Reopen Folder in Container`._ - -The devcontainter comes with some useful tasks to help you with development, you can start these tasks by opening the command pallet and select `Tasks: Run Task` then select the task you want to run. - -Running tasks like `Preview` can be restarted by opening the command pallet and selecting `Tasks: Restart Running Task`, then select the task you want to restart. - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -_Windows users should be sure to clone to a path that inside the WSL (ex: ~/)._ - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv venv -$ source venv/bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```bash -$ hass -``` - -## Logging - -By default logging in Home Assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` diff --git a/website/versioned_docs/version-0.100.0/external_api_rest.md b/website/versioned_docs/version-0.100.0/external_api_rest.md deleted file mode 100644 index 273537f1..00000000 --- a/website/versioned_docs/version-0.100.0/external_api_rest.md +++ /dev/null @@ -1,552 +0,0 @@ ---- -title: REST API -id: version-0.100.0-external_api_rest -original_id: external_api_rest ---- - -Home Assistant provides a RESTful API on the same port as the web frontend. (default port is port 8123). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -* http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -* http://IP_ADDRESS:8123/api/ is a RESTful API. - -The API accepts and returns only JSON encoded objects. - -All API calls have to be accompanied by the header `Authorization: Bearer ABCDEFGH`, where `ABCDEFGH` is replaced by your token. You can obtain a token ("Long-Lived Access Token") by logging into the frontend using a web browser, and going to [your profile](https://www.home-assistant.io/docs/authentication/#your-account-profile) `http://IP_ADDRESS:8123/profile`. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```bash -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. - -```python -from requests import get - -url = 'http://localhost:8123/ENDPOINT' -headers = { - 'Authorization': 'Bearer ABCDEFGH', - 'content-type': 'application/json', -} - -response = get(url, headers=headers) -print(response.text) -``` -Another option is to use the Restful Command component https://www.home-assistant.io/components/rest_command/ in a Home Assistant automation or script. - -```yaml -turn_light_on: - url: http://localhost:8123/api/states/light.study_light - method: POST - headers: - authorization: 'Bearer ABCDEFGH' - content-type: 'application/json' - payload: '{"state":"on"}' -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on one or more entities - comma separated. -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates a state. You can create any state that you want, it does not have to be backed by an entity in Home Assistant. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/config/core/check_config - -Trigger a check of `configuration.yaml`. No additional data needs to be passed in with this request. - -If the check is successful, the following will be returned: - -```javascript -{ - "errors": null, - "result": "valid" -} -``` - -If the check fails, the errors attribute in the object will list what caused the check to fail. For example: - -```javascript -{ - "errors": "Integration not found: frontend:", - "result": "invalid" -} -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance.
- -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` diff --git a/website/versioned_docs/version-0.100.0/hassio_hass.md b/website/versioned_docs/version-0.100.0/hassio_hass.md deleted file mode 100644 index a23a16fc..00000000 --- a/website/versioned_docs/version-0.100.0/hassio_hass.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Hass.io <> Home Assistant integration development -sidebar_label: HASS Integration development -id: version-0.100.0-hassio_hass -original_id: hassio_hass ---- - -These steps will help you connect your local Home Assistant to a remote Hass.io instance. You can then make changes locally to either the Hass.io component or the frontend and test it out against a real instance. - -For this guide, we're going to assume that you have an Hass.io instance up and running. If you don't, you can use the generic installation method to install it inside a [virtual machine](https://github.com/home-assistant/hassio-build/tree/master/install#install-hassio). - -## API Access - -To develop for the frontend, we're going to need API access to the supervisor. - -- Add our developer Add-on repository: https://github.com/home-assistant/hassio-addons-development -- Install the Add-on "Remote API proxy" - -For some API commands you need explicit the Home Assistant API token, but 99% of the functionality work with `Remote API proxy`. This token change sometimes but you can read the current legal token on host system with: -```sh -$ docker inspect homeassistant | grep HASSIO_TOKEN -``` - - ## Having Home Assistant connect to remote Hass.io - - The connection with the supervisor is hidden inside the host and is only accessible from applications running on the host. So to make it accessible for our Home Assistant instance we will need to route the connection to our computer running Home Assistant. We're going to do this by forwarding the API with "Remote API proxy" add-on. - -First, make sure Home Assistant will load the Hass.io component by adding `hassio:` to your `configuration.yaml` file. Next, we will need to tell the local Home Assistant instance how to connect to the remote Hass.io instance. We do this by setting the `HASSIO` and `HASSIO_TOKEN` environment variables when starting Home Assistant. Note that the `HASSIO` value is not the same as the one that we saw above and the `HASSIO_TOKEN` is available inside log output of "Remote API Add-on" (This changes every restart of the add-on!). - -```bash -HASSIO=:80 HASSIO_TOKEN= hass -``` - -Voila. Your local Home Assistant installation will now connect to a remote Hass.io instance. - -## Frontend development - -> This requires Home Assistant 0.71 or later. - -We need a couple more steps to do frontend development. First, make sure you have a Home Assistant frontend development set up ([instructions](frontend_index.md)). - -Update the Hass.io component configuration in your `configuration.yaml` to point at the frontend repository: - -```yaml -# configuration.yaml -hassio: - development_repo: /home/paulus/dev/hass/home-assistant-polymer -``` - -To build a local version of the Hass.io panel, go to the frontend repository and run: - -```bash -cd hassio -script/develop -``` - -Now start Home Assistant as discussed in the previous section and it will now connect to the remote Hass.io but show your local frontend. - -Once you have `script/develop` the hassio panel will be rebuilt whenever you make changes to the source files. diff --git a/website/versioned_docs/version-0.101.0/api_lib_auth.md b/website/versioned_docs/version-0.101.0/api_lib_auth.md deleted file mode 100644 index 79476469..00000000 --- a/website/versioned_docs/version-0.101.0/api_lib_auth.md +++ /dev/null @@ -1,265 +0,0 @@ ---- -title: Python Library: Authentication -sidebar_label: Authentication -id: version-0.101.0-api_lib_auth -original_id: api_lib_auth ---- - -The Authentication part of your library is responsible for acquiring authentication and for making authenticated requests. It should not be aware of what is in the requests. - -Authentication comes in many forms, but it generally boils down to that each request is accompanied by an `authorization` header which contains an access token. The access token is generally a string of random numbers/letters. - -Your library should be able to acquire the authentication tokens, update them if necessary and use the authentication to make requests. It should not offer features to store the authentication data. - -Because authentication is going to be stored by the developer, it is important that you return the authentication to the developer in a format that can be JSON serializable. A `dict` with primitive types (`str`, `float`, `int`) is recommended. - -If your API can be served from multiple locations, your authentication class should allow the developer to pass in the location of the API. - -## Async example - -Python allows developers to write code that is either synchronous or asynchronous (via `asyncio`). Home Assistant is written in async, but is able to work with synchronous libraries too. We prefer async libraries. - -If you are writing a library in async, we recommend that you use `aiohttp`. It's a modern and mature HTTP library and is easy to use. - -```python -from aiohttp import ClientSession, ClientResponse - - -class Auth: - """Class to make authenticated requests.""" - - def __init__(self, websession: ClientSession, host: str, , access_token: str): - """Initialize the auth.""" - self.websession = websession - self.host = host - self.access_token = access_token - - async def request(self, method: str, path: str, **kwargs) -> ClientResponse: - """Make a request.""" - headers = kwargs.get('headers') - - if headers is None: - headers = {} - else: - headers = dict(headers) - - headers["authorization"] = self.access_token - - return await self.websession.request( - method, - f"{self.host}/{path}", - **kwargs, - headers=headers, - ) -``` - -To use this class, you will need to create an aiohttp ClientSession and pass it together with the API info to the constructor. - -```python -import asyncio -import aiohttp - -from my_package import Auth - - -async def main(): - async with aiohttp.ClientSession() as session: - auth = Auth(session, "http://example.com/api", "secret_access_token") - - # This will fetch data from http://example.com/api/lights - resp = await auth.request('get', 'lights') - print("HTTP response status code", resp.status) - print("HTTP response JSON content", await resp.json()) - -asyncio.run(main()) -``` - -## Sync example - -```python -import requests - - -class Auth: - """Class to make authenticated requests.""" - - def __init__(self, host: str, , access_token: str): - """Initialize the auth.""" - self.host = host - self.access_token = access_token - - async def request(self, method: str, path: str, **kwargs) -> requests.Response: - """Make a request.""" - headers = kwargs.get('headers') - - if headers is None: - headers = {} - else: - headers = dict(headers) - - headers["authorization"] = self.access_token - - return requests.request( - method, - f"{self.host}/{path}", - **kwargs, - headers=headers, - ) -``` - -To use this class, construct the class with the API info. - -```python -from my_package import Auth - - -auth = Auth("http://example.com/api", "secret_access_token") - -# This will fetch data from http://example.com/api/lights -resp = auth.request('get', 'lights') -print("HTTP response status code", resp.status_code) -print("HTTP response JSON content", resp.json()) -``` - -## OAuth2 - -OAuth2 is a [standardized version](https://tools.ietf.org/html/rfc6749) of an authentication schema leveraging refresh and access tokens. The access token expires within a short period of time after being issued. The refresh token can be used to acquire new access tokens. - -Refreshing access tokens relies on a client ID and secret, which might be held by an external service. We need to structure the authentication class to be able to allow the developer to implement their own token refresh logic. - -Home Assistant ships with the Home Assistant Cloud Account Linking service, a free cloud service to allow users to quickly connect accounts using OAuth2. Home Assistant has easy to use tools built-in to allow users to configure OAuth2-based integrations. For more info, [read here](config_entries_config_flow_handler.md#configuration-via-oauth2). These built-in tools work best if your library is implemented like the examples below. - -### Async example - -```python -from abc import ABC, abstractmethod - - -class AbstractAuth(ABC): - """Abstract class to make authenticated requests.""" - - def __init__(self, websession: ClientSession, host: str): - """Initialize the auth.""" - self.websession = websession - self.host = host - - @abstractmethod - async def async_get_access_token(self) -> str: - """Return a valid access token.""" - - async def request(self, method, url, **kwargs) -> ClientResponse: - """Make a request.""" - headers = kwargs.get('headers') - - if headers is None: - headers = {} - else: - headers = dict(headers) - - access_token = await self.async_get_access_token() - headers["authorization"] = f"Bearer {access_token}" - - return await self.websession.request( - method, - f"{self.host}/{url}", - **kwargs, - headers=headers, - ) -``` - -Now the developer that is using your library will have to implement the abstract method for getting the access token. Let's assume that the developer has their own token manager class. - -```python -from my_package import AbstractAuth - - -class Auth(AbstractAuth): - - def __init__(self, websession: ClientSession, host: str, token_manager): - """Initialize the auth.""" - super().__init__(websession, host) - self.token_manager = token_manager - - async def async_get_access_token(self) -> str: - """Return a valid access token.""" - if self.token_manager.is_token_valid(): - return self.token_manager.access_token - - await self.token_manager.fetch_access_token() - await self.token_manager.save_access_token() - - return self.token_manager.access_token -``` - -### Sync example - -If you are using `requests`, we recommend that you use the `requests_oauthlib` package. Below is an example that works with a local client ID and secret but also allows outsourcing token fetching to Home Assistant. - -```python -from typing import Optional, Union, Callable, Dict - -from requests import Response -from requests_oauthlib import OAuth2Session -from oauthlib.oauth2 import TokenExpiredError - - -class Auth: - def __init__( - self, - host: str, - token: Optional[Dict[str, str]] = None, - client_id: str = None, - client_secret: str = None, - token_updater: Optional[Callable[[str], None]] = None, - ): - self.host = host - self.client_id = client_id - self.client_secret = client_secret - self.token_updater = token_updater - - self._oauth = OAuth2Session( - client_id=client_id, - client_secret=client_secret, - token=token, - token_updater=token_updater, - ) - - def refresh_tokens(self) -> Dict[str, Union[str, int]]: - """Refresh and return new tokens.""" - token = self._oauth.refresh_token(f"{self.host}/auth/token") - - if self.token_updater is not None: - self.token_updater(token) - - return token - - def request(self, method: str, path: str, **kwargs) -> Response: - """Make a request. - - We don't use the built-in token refresh mechanism of OAuth2 session because - we want to allow overriding the token refresh logic. - """ - url = f"{self.host}/{path}" - try: - return getattr(self._oauth, method)(url, **kwargs) - except TokenExpiredError: - self._oauth.token = self.refresh_tokens() - - return getattr(self._oauth, method)(url, **kwargs) -``` - -A developer will now be able to override the refresh token function to route it via their own external service. - -```python -from my_package import AbstractAuth - - -class Auth(AbstractAuth): - - def refresh_tokens(self) -> Dict[str, Union[str, int]]: - """Refresh and return new tokens.""" - self.token_manager.fetch_access_token() - self.token_manager.save_access_token() - - return self.token_manager.access_token -``` diff --git a/website/versioned_docs/version-0.101.0/api_lib_data_models.md b/website/versioned_docs/version-0.101.0/api_lib_data_models.md deleted file mode 100644 index 91dcf21c..00000000 --- a/website/versioned_docs/version-0.101.0/api_lib_data_models.md +++ /dev/null @@ -1,148 +0,0 @@ ---- -title: Python Library: Modelling Data -sidebar_label: Modelling Data -id: version-0.101.0-api_lib_data_models -original_id: api_lib_data_models ---- - -Now that we have authentication going, we can start making authenticated requests and fetch data! - -When modelling the data, it is important that we expose the data from the API in the same structure as that the API offers it. Some API designs might not make a lot of sense or contain typos. It is important that we still represent them in our objects. This makes it easy for developers using your library to follow the API documentation and know how it will work in your library. - -API libraries should try to do as little as possible. So it is okay to represent data structures as classes, but you should not transform data from one value into another. For example, you should not implement conversion between Celsius and Fahrenheit temperatures. This involves making decisions on precisions of results and should therefore be left to the developer using the library. - -For this example we're going to model an async library for a Rest API named ExampleHub that has two endpoints: - -- get `/light/`: query the information of a single light. - - ```json - { - "id": 1234, - "name": "Example Light", - "is_on": true - } - ``` - -- post `/light/`: control the light. Example JSON to send: `{ "is_on": false }`. Responds with the new state of the light. - -- get `/lights`: return a list of all lights - ```json - [ - { - "id": 1234, - "name": "Example Light", - "is_on": true - }, - { - "id": 5678, - "name": "Example Light 2", - "is_on": false - } - ] - ``` - -As this API represents lights, we're first going to create a class to represent a light. - -```python -from .auth import Auth - - -class Light: - """Class that represents a Light object in the ExampleHub API.""" - - def __init__(self, raw_data: dict, auth: Auth): - """Initialize a light object.""" - self.raw_data = raw_data - self.auth = auth - - # Note: each property name maps the name in the returned data - - @property - def id(self) -> int: - """Return the ID of the light.""" - return self.raw_data['id'] - - @property - def name(self) -> str: - """Return the name of the light.""" - return self.raw_data['name'] - - @property - def is_on(self) -> bool: - """Return if the light is on.""" - return self.raw_data['id'] - - async def async_control(self, is_on: bool): - """Control the light.""" - resp = await self.auth.request('post', f'light/{self.id}', json={ - 'is_on': is_on - }) - resp.raise_for_status() - self.raw_data = await resp.json() - - async def async_update(self): - """Update the light data.""" - resp = await self.auth.request('get', f'light/{self.id}') - resp.raise_for_status() - self.raw_data = await resp.json() -``` - -Now that we have a light class, we can model the root of the API, which provides the entry points into the data. - -```python -from typing import List - -from .auth import Auth -from .light import Light - - -class ExampleHubAPI: - """Class to communicate with the ExampleHub API.""" - - def __init__(self, auth: Auth): - """Initialize the API and store the auth so we can make requests.""" - self.auth = auth - - async def async_get_lights(self) -> List[Light]: - """Return the lights.""" - resp = await self.auth.request('get', 'lights') - resp.raise_for_status() - return [ - Light(light_data, self.auth) - for light_data in await resp.json() - ] - - async def async_get_light(self, light_id) -> Light: - """Return the lights.""" - resp = await self.auth.request('get', f'light/{light_id}') - resp.raise_for_status() - return Light(await resp.json(), self.auth) -``` - -With these two files in place, we can now control our lights like this: - -```python -import asyncio -import aiohttp - -from my_package import Auth, ExampleHubAPI - - -async def main(): - async with aiohttp.ClientSession() as session: - auth = Auth(session, "http://example.com/api", "secret_access_token") - api = ExampleHubAPI(auth) - - lights = await api.async_get_lights() - - # Print light states - for light in lights: - print(f"The light {light.name} is {light.is_on}") - - # Control a light. - light = lights[0] - await light.async_control(not light.is_on) - - -asyncio.run(main()) -``` diff --git a/website/versioned_docs/version-0.101.0/api_lib_index.md b/website/versioned_docs/version-0.101.0/api_lib_index.md deleted file mode 100644 index 9f6640c8..00000000 --- a/website/versioned_docs/version-0.101.0/api_lib_index.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Building a Python library for an API -sidebar_label: Introduction -id: version-0.101.0-api_lib_index -original_id: api_lib_index ---- - -One of the foundational rules of Home Assistant is that we do not include any protocol specific code. Instead, this code should be put into a standalone Python library and published to PyPI. This guide will describe how to get started with this! - -For this guide we're going to assume that we're building a library for a Rest API that is accessible over HTTP and returning data structured as JSON objects. This is the most common type of API that we see. These APIs can either be accessible on the device itself, or in the cloud. - -This guide is not a perfect fit for every API. You might have to tweak the examples. - -> If you are a manufacturer designing a new API for your product, [please read about the best type of API to add to your products here](https://www.home-assistant.io/blog/2016/02/12/classifying-the-internet-of-things/#local-device-pushing-new-state). - -HTTP API requests consist of four different parts: - -- The URL. This is the path that we fetch data from. With a Rest API the URL will uniquely identify the resource. Examples of urls are `http://example.com/api/lights` and `http://example.com/api/light/1234`. -- The HTTP method. This defines what we want from the API. The most common ones are: - - `GET` for when we want to get information like the state of a light - - `POST` for if we want something to be done (ie turn on a light) -- The body. This is the data that we sent to the server to identify what needs to be done. This is how we send the command in the case of a `POST` request. -- The headers. This contains metadata to describe your request. This will used to attach the authorization to the request. - -## Structuring the library - -Our library will consist of two different parts: - -- **Authentication:** Responsible for making authenticated HTTP requests to the API endpoint and returning the results. This is the only piece of code that will actually interact with the API. -- **Data models:** Represent the data and offer commands to interact with the data. - -## Trying your library inside Home Assistant - -You will need to run an editable version of your library if you want to try your library in Home Assistant before it is publised to PyPI. - -Do so by going to your Home Assistant development environment, activating the virtual environment and typing: - -``` -pip3 install -e ../my_lib_folder -``` - -Now run Home Assistant without installing dependencies from PyPI to avoid overriding your package. - -``` -hass --skip-pip -``` diff --git a/website/versioned_docs/version-0.101.0/config_entries_config_flow_handler.md b/website/versioned_docs/version-0.101.0/config_entries_config_flow_handler.md deleted file mode 100644 index 79b23df6..00000000 --- a/website/versioned_docs/version-0.101.0/config_entries_config_flow_handler.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Integration Configuration -sidebar_label: Configuration -id: version-0.101.0-config_entries_config_flow_handler -original_id: config_entries_config_flow_handler ---- - -Integrations can be set up via the user interface by adding support for a config config to create a config entry. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like Hass.io). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -## Updating the manifest - -You need to update your integrations manifest to inform Home Assistant that your integration has a config flow. This is done by adding `config_flow: true` to your manifest ([docs](creating_integration_manifest.md#config-flow)). - -## Defining your config flow - -Config entries uses the [data flow entry framework](data_entry_flow_index.md) to define their config flows. The config flow needs to be defined in the file `config_flow.py` in your integration folder, extend `homeassistant.config_entries.ConfigFlow` and pass a `domain` key as part of inheriting `ConfigFlow`. - -```python -from homeassistant import config_entries -from .const import DOMAIN - -class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): -``` - -## Defining steps - -Your config flow will need to define steps of your configuration flow. The docs for [Data Entry Flow](data_entry_flow_index.md) describe the different return values of a step. Here is an example on how to define the `user` step. - -```python -class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): - - async def async_step_user(self, info): - if info is not None: - # process info - - return self.async_show_form( - step_id='user', - data_schema=vol.Schema({ - vol.Required('password'): str - }) - ) -``` - -There are a few step names reserved for system use: - -| Step name | Description | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `user` | Invoked when a user initiates a flow via the user interface. | -| `zeroconf` | Invoked if your integration has been discovered via Zeroconf/mDNS as specified [using `zeroconf` in the manifest](creating_integration_manifest.md#zeroconf). | -| `homekit` | Invoked if your integration has been discovered via HomeKit as specified [using `homekit` in the manifest](creating_integration_manifest.md#homekit). | -| `ssdp` | Invoked if your integration has been discovered via SSDP/uPnP as specified [using `ssdp` in the manifest](creating_integration_manifest.md#ssdp). | -| `discovery` | _DEPRECATED_ Invoked if your integration has been discovered by the discovery integration. | - -## Discovery steps - -When an integration is discovered, their respective discovery step is invoked with the discovery information. The step will have to check the following things: - -- Make sure there are no other instances of this config flow in progress of setting up the discovered device. This can happen if there are multiple ways of discovering that a device is on the network. -- Make sure that the device is not already set up. -- Invoking a discovery step should never result in a finished flow and a config entry. Always confirm with the user. - -## Discoverable integrations that require no authentication - -If your integration is discoverable without requiring any authentication, you'll be able to use the Discoverable Flow that is built-in. This flow offers the following features: - -- Detect if devices/services can be discovered on the network before finishing the config flow. -- Support all manifest-based discovery protocols. -- Limit to only 1 config entry. It is up to the config entry to discover all available devices. - -To get started, run `python3 -m script.scaffold config_flow_discovery` and follow the instructions. This will create all the boilerplate necessary to configure your integration using discovery. - -## Configuration via OAuth2 - -Home Assistant has built-in support for integrations that offer account linking using [the OAuth2 authorization framework](https://tools.ietf.org/html/rfc6749). To be able to leverage this, you will need to structure your Python API library in a way that allows Home Assistant to be responsible for refreshing tokens. See our [API library guide](api_lib_index.md) on how to do this. - -The built-in OAuth2 support works out of the box with locally configured client ID / secret and with the Home Assistant Cloud Account Linking service. This service allows users to link their account with a centrally managed client ID/secret. If you want your integration to be part of this service, reach out to us at [hello@home-assistant.io](mailto:hello@home-assistant.io). - -To get started, run `python3 -m script.scaffold config_flow_oauth2` and follow the instructions. This will create all the boilerplate necessary to configure your integration using OAuth2. - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` - -When the translations are merged into Home Assistant, they will be automatically uploaded to [Lokalise](https://lokalise.co/) where the translation team will help to translate them in other languages. [More info on translating Home Assistant.](internationalization_translation.md) diff --git a/website/versioned_docs/version-0.101.0/config_entries_options_flow_handler.md b/website/versioned_docs/version-0.101.0/config_entries_options_flow_handler.md deleted file mode 100644 index 1b293ac3..00000000 --- a/website/versioned_docs/version-0.101.0/config_entries_options_flow_handler.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Integration Configuration Options -sidebar_label: Configuration Options -id: version-0.101.0-config_entries_options_flow_handler -original_id: config_entries_options_flow_handler ---- - -An integration that is configured via a config entry can expose options to the user to allow tweaking behavior of the integration, like which devices or locations should be integrated. - -Config Entry Options uses the [Data Flow Entry framework](data_entry_flow_index.md) to allow users to update a config entries options. Components that want to support config entry options will need to define an Options Flow Handler. - -## Options support - -For an integration to support options it needs to have an `async_get_options_flow` method in its config flow handler. Calling it will return an instance of the components options flow handler. - -```python -@staticmethod -@callback -def async_get_options_flow(config_entry): - return OptionsFlowHandler() -``` - -## Flow handler - -The Flow handler works just like the config flow handler, except that the first step in the flow will always be `async_step_init`. - -```python -class OptionsFlowHandler(config_entries.OptionsFlow): - - async def async_step_init(self, user_input=None): - """Manage the options.""" - if user_input is not None: - return self.async_create_entry(title="", data=user_input) - - return self.async_show_form( - step_id="init", - data_schema=vol.Schema( - { - vol.Required( - "show_things", - default=self.config_entry.options.get("show_things"), - ): bool - } - ), - ) -``` - -## Signal updates - -If the component should act on updated options, you can register an update listener to the config entry that will be called when the entry is updated. - -```python -entry.add_update_listener(update_listener) -``` - -The Listener shall be an async function that takes the same input as async_setup_entry. Options can then be accessed from `entry.options`. - -```python -async def update_listener(hass, entry): -``` diff --git a/website/versioned_docs/version-0.101.0/data_entry_flow_index.md b/website/versioned_docs/version-0.101.0/data_entry_flow_index.md deleted file mode 100644 index 40e01ca9..00000000 --- a/website/versioned_docs/version-0.101.0/data_entry_flow_index.md +++ /dev/null @@ -1,288 +0,0 @@ ---- -title: Data Entry Flow -sidebar_label: Introduction -id: version-0.101.0-data_entry_flow_index -original_id: data_entry_flow_index ---- - -Data Entry Flow is a data entry framework that is part of Home Assistant. Data entry is done via data entry flows. A flow can represent a simple login form or a multi-step setup wizard for a component. A Flow Manager is managing all flows that are in progress and handles creation of new flows. - -Data Entry Flow is being used in Home Assistant to create config entries. - -## Flow Manager - -This is the class that manages the flows that are in progress. When instantiating one, you pass in two async callbacks: - -```python -async def async_create_flow(handler, context=context, data=data) -``` - -The manager delegates instantiating of config flow handlers to this async callback. This allows the parent of the manager to define their own way of finding handlers and preparing a handler for instantiation. For example, in the case of the config entry manager, it will make sure that the dependencies and requirements are setup. - -```python -async def async_finish_flow(flow, result) -``` - -This async callback is called when a flow is finished or aborted. i.e. `result['type'] in [RESULT_TYPE_CREATE_ENTRY, RESULT_TYPE_ABORT]`. The callback function can modify result and return it back, if the result type changed to `RESULT_TYPE_FORM`, the flow will continue running, display another form. - -If the result type is `RESULT_TYPE_FORM`, the result should like: -```python -{ - # The result type of the flow - 'type': RESULT_TYPE_FORM, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # name of the step, flow.async_step_[step_id] will be called when form submitted - 'step_id': 'init', - # a voluptuous schema to build and validate user input - 'data_schema': vol.Schema(), - # an errors dict, None if no errors - 'errors': errors, - # a detail information about the step - 'description_placeholders': description_placeholders, -} -``` - -If the result type is `RESULT_TYPE_CREATE_ENTRY`, the result should like: -```python -{ - # Data schema version of the entry - 'version': 2, - # The result type of the flow - 'type': RESULT_TYPE_CREATE_ENTRY, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # title and data as created by the handler - 'title': 'Some title', - 'result': { - 'some': 'data' - }, -} -``` - -If the result type is `RESULT_TYPE_ABORT`, the result should like: -```python -{ - # The result type of the flow - 'type': RESULT_TYPE_ABORT, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # the abort reason - 'reason': 'already_configured', -} -``` - - -## Flow Handler - -Flow handlers will handle a single flow. A flow contains one or more steps. When a flow is instantiated, the `FlowHandler.init_step` step will be called. Each step has three different possible results: "Show Form", "Abort" and "Create Entry". - -At a minimum, each flow handler will have to define a version number and a step. This doens't have to be `init`, as `async_create_flow` can assign `init_step` depends on diffreent workflow, for example in configuration, `context.source` will be use as `init_step`. - -The bare minimum config flow: - -```python -from homeassistant import data_entry_flow - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - # The schema version of the entries that it creates - # Home Assistant will call your migrate method if the version changes - # (this is not implemented yet) - VERSION = 1 - - async def async_step_user(self, user_input=None): - # Do something -``` - -### Show Form - -This result type will show a form to the user to fill in. You define the current step, the schema of the data (using voluptuous) and optionally a dictionary of errors. Title and description of the step will be provided via the translation file. Where this is defined depends on the context of the data entry flow. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema) - ) -``` - -After the user has filled in the form, the step method will be called again and the user input is passed in. Your step will only be called if the user input passes your data schema. When the user passes in data, you will have to do extra validation of the data. For example, you can verify that the passed in username and password are valid. - -If something is wrong, you can return a dictionary with errors. Each key in the error dictionary refers to a field name that contains the error. Use the key `base` if you want to show an error unrelated to a specific field. The specified errors need to refer to a key in a translation file. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # See next section on create entry usage - return self.create_entry(...) - - errors['base'] = 'auth_error' - - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema), - errors=errors - ) -``` - -#### Multi-step flows - -If the user input passes validation, you can again return one of the three return values. If you want to navigate the user to the next step, return the return value of that step: - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_init(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # Store info to use in next step - self.init_info = user_input - # Return the form of the next step - return await self.async_step_account() - - ... -``` - -### Create Entry - -When the result is "Create Entry", an entry will be created and passed to the parent of the flow manager. A success message is shown to the user and the flow is finished. You create an entry by passing a title and data. The title can be used in the UI to indicate to the user which entry it is. Data can be any data type, as long as it is JSON serializable. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - return self.create_entry( - title='Title of the entry', - data={ - 'something_special': user_input['username'] - } - ) -``` - -### Abort - -When a flow cannot be finished, you need to abort it. This will finish the flow and inform the user that the flow has finished. Reasons for a flow to not be able to finish can be that a device is already configured or not compatible with Home Assistant. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - return self.async_abort( - reason='not_supported' - ) -``` - -### External Step & External Step Done - -It is possible that a user needs to finish a config flow by doing actions on an external website. For example, setting up an integration by being redirected to an external webpage. This is commonly used by integrations that use OAuth2 to authorize a user. - -_The example is about config entries, but works with other parts that use data entry flows too._ - -The flow works as follows: - - 1. User starts config flow in Home Assistant - 2. Config flow prompts user to finish the flow on an external website - 3. User opens the external website - 4. Upon completion of the external step, the user's browser will be redirected to a Home Assistant endpoint to deliver the response. - 5. The endpoint validates the response, and upon validation, marks the external step as done and returns JavaScript code to close the window: ``. - - To be able to route the result of the external step to the Home Assistant endpoint, you will need to make sure the config flow ID is included. If your external step is an OAuth2 flow, you can leverage the oauth2 state for this. This is a variable that is not interpreted by the authorization page but is passed as-is to the Home Assistant endpoint. - 6. The window closes and the Home Assistant user interface with the config flow will be visible to the user again. - 7. The config flow has automatically advanced to the next step when the external step was marked as done. The user is prompted with the next step. - -Example configuration flow that includes an external step. - -```python -from homeassistant import config_entries - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - VERSION = 1 - data = None - - async def async_step_user(self, user_input=None): - if not user_input: - return self.async_external_step( - step_id='user', - url='https://example.com/?config_flow_id={}'.format( - self.flow_id - ), - ) - - self.data = user_input - return self.async_external_step_done(next_step_id='finish') - - async def async_step_finish(self, user_input=None): - return self.async_create_entry( - title=self.data['title'], - data=self.data - ) -``` - -Avoid doing work based on the external step data before you return an `async_mark_external_step_done`. Instead, do the work in the step that you refer to as `next_step_id` when marking the external step done. This will give the user a better user experience by showing a spinner in the UI while the work is done. - -If you do the work inside the authorize callback, the user will stare at a blank screen until that all of a sudden closes because the data has forwarded. If you do the work before marking the external step as done, the user will still see the form with the "Open external website" button while the background work is being done. That too is undesirable. - -Example code to mark an external step as done: - -```python -from homeassistant import data_entry_flow - -async def handle_result(hass, flow_id, data): - result = await hass.config_entries.async_configure(flow_id, data) - - if result['type'] == data_entry_flow.RESULT_TYPE_EXTERNAL_STEP_DONE: - return "success!" - else: - return "Invalid config flow specified" -``` - -## Translations - -Data entry flows depend on translations for showing the text in the forms. It depends on the parent of a data entry flow manager where this is stored. - -## Initializing a config flow from an external source - -You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing a flow: - -```python -await flow_mgr.async_init('hue', context={'source': data_entry_flow.SOURCE_DISCOVERY}, data=discovery_info) -``` - -The config flow handler will not start with the `init` step. Instead, it will be instantiated with a step name equal to the source. The step should follow the same return values as a normal step. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` diff --git a/website/versioned_docs/version-0.101.0/documentation_create_page.md b/website/versioned_docs/version-0.101.0/documentation_create_page.md deleted file mode 100644 index 42f0e8b6..00000000 --- a/website/versioned_docs/version-0.101.0/documentation_create_page.md +++ /dev/null @@ -1,137 +0,0 @@ ---- -title: Create a new page -id: version-0.101.0-documentation_create_page -original_id: documentation_create_page ---- - -For a platform or integration page, the fastest way is to make a copy of an existing page and edit it. The [Integration overview](https://www.home-assistant.io/components/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages. - -Please honor the [Standards](documentation_standards.md) we have for the documentation. - -If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers. - -```text ---- -title: "Awesome Sensor" -description: "home-assistant.io web presence" -ha_release: "0.38" -ha_category: Sensor -ha_iot_class: "Local Polling" -ha_qa_scale: silver -ha_config_flow: true ---- - -Content... Written in markdown. - -### Title Header -... -``` - -Additional keys for the file header: - -- `logo`: Please check the separate section below. -- `ha_release`: The release when the integration was included, e.g., "0.38". If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`. -- `ha_category`: This entry is used to group the integration on the [Integration overview](https://www.home-assistant.io/components/). -- `ha_iot_class`: [IoT class](https://www.home-assistant.io/blog/2016/02/12/classifying-the-internet-of-things) is the classifier for the device's behavior. -- `ha_qa_scale`: [Quality scale](https://www.home-assistant.io/docs/quality_scale/) is the representation of the integration's quality. -- `ha_config_flow`: Set to `true` if the integration has a [Data Entry Flow](https://developers.home-assistant.io/docs/en/data_entry_flow_index.html), omit otherwise. - -There are [pre-defined variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation. - -A couple of points to remember: - -- Document the needed steps to retrieve API keys or access token for the third party service or device if needed. -- Add screenshots to support the user where it makes sense. -- Add the type of the device(s) (incl. firmware) you have tested when you know that there are multiple out there. - -### Configuration - -Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file. - -The **Configuration Variables** section must use the `{% configuration %} ... {% endconfiguration %}` tag. - -```text -{% configuration %} -api_key: - description: The API key to access the service. - required: true - type: string -name: - description: Name to use in the frontend. - required: false - default: The default name to use in the frontend. - type: string -monitored_conditions: - description: Conditions to display in the frontend. - required: true - type: map - keys: - weather: - description: A human-readable text summary. - temperature: - description: The current temperature. -{% endconfiguration %} -``` - -Available keys: - -- **`description:`**: That the variable is about. -- **`required:`**: If the variable is required. - -```text -required: true #=> Required -required: false #=> Optional -required: inclusive #=> Inclusive -required: exclusive #=> Exclusive -required: any string here #=> Any string here -``` -- **`type:`**: The type of the variable. Allowed entries: `boolean`, `string`, `integer`, `float`, `time`, `template`, `device_class`, `icon` or `map`/`list` (for a list of entries). For multiple possibilities use `[string, integer]`. If you use `map`/`list` then should define `keys:` (see the [`template` sensor](https://www.home-assistant.io/components/sensor.template/) for an example). If you use `boolean`, then `default:` must be defined. -- **`default:`**: The default value for the variable. - -### Embedding Code - -You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in back-ticks. - -When you're writing code that is to be executed on the terminal, do not prefix them with `$`, since this makes it hard to copy and paste the commands. However, an exception is made when there is a need to distinguish between typed commands and command output. In those cases, prefixing the commands with a `$` is required. - -### Templates - -For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) [Jinja](http://jinja.pocoo.org/) is used. Check the [Documentation Standards](documentation_standards.md) for further details. - -If you are don't escape templates then they will be rendered and appear blank on the website. - -### HTML - -The direct usage of HTML is supported but not recommended. The note boxes are an exception. - -```html -
- You need to enable telnet on your router. -
-``` - -Please note, if you want to use Markdown inside an HTML block, it has to be surrounded by a new line. - -```html -
- - You need to enable [**telnet**](https://en.wikipedia.org/wiki/Telnet) on your router. - -
-``` - -### Images, icons and logos - -The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent. - -| Type | Location | -| :----------- |:----------------------------------------------| -| logos | source/images/supported_brands | -| blog | source/images/blog | -| screenshots | source/images/components | - -Not everything (product, integration, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/). - -### Linking From The Sidebar - -If you are adding a new page that requires linking from the sidebar, you need to edit the `docs_navigation.html` file in `source/_includes/asides/docs_navigation.html`. diff --git a/website/versioned_docs/version-0.101.0/documentation_index.md b/website/versioned_docs/version-0.101.0/documentation_index.md deleted file mode 100644 index 631c600a..00000000 --- a/website/versioned_docs/version-0.101.0/documentation_index.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Documentation -id: version-0.101.0-documentation_index -original_id: documentation_index ---- - -The user documentation is located at [https://www.home-assistant.io](https://www.home-assistant.io). This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. You work on your change and propose it via a Pull Request (PR). - -Once you've created a Pull Request (PR), you can see a preview of the proposed changes by clicking *Details* against Netlify checker in the checkers section of the PR as soon as deployment is complete. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process of working on the website is no different from working on Home Assistant itself. - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.5.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` (You might have to run this command as `sudo`). - -- Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` -- Shortcut for Debian/Ubuntu: `$ sudo apt-get install ruby ruby-dev ruby-bundler ruby-json g++ zlib1g-dev && bundle` - -- Fork the home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.io). -- In your home-assistant.io root directory, run `$ bundle` to install the gems you need. - -Then you can work on the documentation: - -- Run `bundle exec rake generate` to generate the very first preview. This will take a minute. -- Create/edit/update a page. The integration/platforms documentation is located in `source/_integrations/`. `source/_docs/` contains the Home Assistant documentation itself. -- Test your changes to home-assistant.io locally: run `bundle exec rake preview` and navigate to [http://127.0.0.1:4000](http://127.0.0.1:4000). While this command is working, any changes to a file are automatically detected and will update the affected pages. You will have to manually reload them in the browser though. -- Create a Pull Request (PR) against the **next** branch of home-assistant.io if your documentation is a new feature, platform, or integration. -- Create a Pull Request (PR) against the **current** branch of home-assistant.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -The site generated by `bundle exec rake` is only available locally. If you are developing on a headless machine, use port forwarding: - -```bash -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` - -## Speeding up site generation - -Every release we post long changelogs to the website. This slows down generation of the website a bit. We've include some tools to temporarily exclude integrations and blog posts that you're not working on out of the way. - -```bash -bundle exec rake isolate[filename-of-blogpost-or-integration] -``` - -When you're done working on the site, run the following command to move the pages back again: - -```bash -bundle exec rake integrate -``` diff --git a/website/versioned_docs/version-0.101.0/documentation_standards.md b/website/versioned_docs/version-0.101.0/documentation_standards.md deleted file mode 100644 index 092f7f45..00000000 --- a/website/versioned_docs/version-0.101.0/documentation_standards.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Standards -id: version-0.101.0-documentation_standards -original_id: documentation_standards ---- - -To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation. - -## General Documentation - -* The language of the documentation should be American-English. -* Don't put two spaces after a period and avoid the "Oxford comma". -* There is no limit for the line length. You are allowed to write in a flowing text style. This will make it easier to use the GitHub online editor in the future. -* Be objective and not gender favoring, polarizing, race related or religion inconsiderate. -* The case of brand names, services, protocols, integrations and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select". -* Do not use ALL CAPITALS for emphasis - use italics instead. - -## Integration and Platform Pages - -* The **Configuration Variables** section must use the `{% configuration %}` tag. -* Configuration variables must document the requirement status (`false` or `true`). -* Configuration variables must document the default value, if any. -* Configuration variables must document the accepted value types (see [Configuration variables details](documentation_create_page.md#configuration)). - * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`). -* Use YAML sequence syntax in the sample code if it is supported. -* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated. - * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`. - * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note. -* Integration and platform names should be a link to their respective documentation pages. - -Example configuration block - -```yaml -{% configuration %} -some_key: - description: This is a description of what this key is for. - required: false - type: string - default: Optional default value - leave out if there isn't one -{% endconfiguration %} -``` - -## Templates - -* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the `{% raw %}` tag. -* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`. -* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)): - * `friendly_name` - * Single-line templates: - * `value_template` - * `level_template` - * `icon_template` - * Children of `data_template` -* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks): - * Strings inside of templates: - * States - * Entity IDs - * `unit_of_measurement` -* No whitespace around pipe character (`|`) for Jinja2 filters. -* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}). -* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}). -* Do not quote values for: - * `device_class` - * `platform` - * `condition` - * `service` - -## Renaming Pages - -It can happen that a integration or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old integration/platform name, to the page in a [note](/developers/documentation/create_page/#html). - -```text ---- -... -redirect_from: /getting-started/android/ ---- -``` - -Adding a redirect also applies if you move content around in the [documentation](https://www.home-assistant.io/docs/). - -## Single vs. Double Quotation Marks - -Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required). - -### Examples - -#### Double Quotes Outside, Single Quotes Inside (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}" -``` - -#### Single Quotes Outside, Double Quotes Inside (Invalid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}' -``` - -#### Multi-Line Template (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: >- - {% if trigger.to_state.name == 'Dale\'s Bedroom' %} - Someone's in your base, killing your noobs! - {% else %} - It's just another door. - {% endif %} -``` diff --git a/website/versioned_docs/version-0.101.0/entity_climate.md b/website/versioned_docs/version-0.101.0/entity_climate.md deleted file mode 100644 index 210378f3..00000000 --- a/website/versioned_docs/version-0.101.0/entity_climate.md +++ /dev/null @@ -1,221 +0,0 @@ ---- -title: Climate Entity -sidebar_label: Climate -id: version-0.101.0-entity_climate -original_id: entity_climate ---- - -A climate entity is a device that controls temperature, humidity, or fans, such as A/C systems and humidifiers. Derive entity platforms from [`homeassistant.components.climate.ClimateDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/climate/__init__.py) - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ----------------------- | ------ | ------------------------------------ | ------------------------------------------------------------------------------------------------------------ | -| temperature_unit | string | `NotImplementedError` | The unit of temperature measurement for the system (`TEMP_CELSIUS` or `TEMP_FAHRENHEIT`). | -| precision | float | Based on `temperature_unit` | The precision of the temperature in the system. Defaults to tenths for TEMP_CELSIUS, whole number otherwise. | -| current_temperature | float | None | The current temperature. | -| current_humidity | float | None | The current humidity. | -| target_temperature | float | None | The temperature currently set to be reached. | -| target_temperature_high | float | None | The upper bound target temperature | -| target_temperature_low | float | None | The lower bound target temperature | -| target_temperature_step | float | None | The supported step size a target temperature can be increased/decreased | -| target_humidity | float | None | The target humidity the device is trying to reach. Requires `SUPPORT_TARGET_HUMIDITY`. | -| max_temp | int | `DEFAULT_MAX_TEMP` (value == 35) | Returns the maximum temperature. | -| min_temp | int | `DEFAULT_MIN_TEMP` (value == 7) | Returns the minimum temperature. | -| max_humidity | int | `DEFAULT_MAX_HUMIDITY` (value == 99) | Returns the maximum humidity. Requires `SUPPORT_TARGET_HUMIDITY`. | -| min_humidity | int | `DEFAULT_MIN_HUMIDITY` (value == 30) | Returns the minimum humidity. Requires `SUPPORT_TARGET_HUMIDITY`. | -| hvac_mode | string | `NotImplementedError()` | The current operation (e.g. heat, cool, idle). Used to determine `state`. | -| hvac_action | string | None | The current HVAC action (heating, cooling) | -| hvac_modes | list | `NotImplementedError()` | List of available operation modes. See below. | -| preset_mode | string | `NotImplementedError()` | The current active preset. Requires `SUPPORT_PRESET_MODE`. | -| preset_modes | list | `NotImplementedError()` | The available presets. Requires `SUPPORT_PRESET_MODE`. | -| fan_mode | string | `NotImplementedError()` | Returns the current fan mode. Requires `SUPPORT_FAN_MODE`. | -| fan_modes | list | `NotImplementedError()` | Returns the list of available fan modes. Requires `SUPPORT_FAN_MODE`. | -| swing_mode | string | `NotImplementedError()` | Returns the fan setting. | -| swing_modes | list | `NotImplementedError()` | Returns the list of available swing modes. | -| is_aux_heat | bool | None | Returns True if an auxiliary heater is on. Requires `SUPPORT_AUX_HEAT`. | -| supported_features | int | `NotImplementedError()` | Bitmap of supported features. See below. | - -### HVAC modes - -You are only allowed to use the built-in HVAC modes. If you want another mode, add a preset instead. - -| Name | Description | -| --------------------- | ------------------------------------------------------------------- | -| `HVAC_MODE_OFF` | The device is turned off. | -| `HVAC_MODE_HEAT` | The device is set to heat to a target temperature. | -| `HVAC_MODE_COOL` | The device is set to cool to a target temperature. | -| `HVAC_MODE_HEAT_COOL` | The device supports heating/cooling to a range | -| `HVAC_MODE_AUTO` | The device is set to a schedule, learned behavior, AI. | -| `HVAC_MODE_DRY` | The device is set to dry/humidity mode. | -| `HVAC_MODE_FAN_ONLY` | The device only has the fan on. No heating or cooling taking place. | - -### HVAC Action - -The HVAC action describes the _current_ action. This is different from the mode, because if a device is set to heat, and the target temperature is already achieved, the device will not be actively heating anymore. - -| Name | Description | -| ------------------- | --------------------- | -| `CURRENT_HVAC_OFF` | Device is turned off. | -| `CURRENT_HVAC_HEAT` | Device is heating. | -| `CURRENT_HVAC_COOL` | Device is cooling. | -| `CURRENT_HVAC_DRY` | Device is dring. | -| `CURRENT_HVAC_IDLE` | Device is idle. | - -### Presets - -A device can have different presets that it might want to show to the user. Common presets are "Away" or "Eco". There are a couple of built-in presets that will offer translations, but you're also allowed to add custom presets. - -| Name | Description | -| ---------- | ------------------------------------------------------ | -| `ECO` | Device is running an energy-saving mode | -| `AWAY` | Device is in away mode | -| `BOOST` | Device turn all valve full up | -| `COMFORT` | Device is in comfort mode | -| `HOME` | Device is in home mode | -| `SLEEP` | Device is prepared for sleep | -| `ACTIVITY` | Device is reacting to activity (e.g. movement sensors) | - -### Fan modes - -A device's fan can have different states. There are a couple of built-in fan modes, but you're also allowed to use custom fan modes. - -| Name | -| ------------- | -| `FAN_ON` | -| `FAN_OFF` | -| `FAN_AUTO` | -| `FAN_LOW` | -| `FAN_MEDIUM` | -| `FAN_HIGH` | -| `FAN_MIDDLE` | -| `FAN_FOCUS` | -| `FAN_DIFFUSE` | - -### Swing modes - -The device fan can have different swing modes that it wants the user to know about/control. - -| Name | Description | -| ------------------ | ------------------------------------------------ | -| `SWING_OFF` | The fan is not swinging. | -| `SWING_VERTICAL` | The fan is swinging vertical. | -| `SWING_HORIZONTAL` | The fan is swinging horizontal. | -| `SWING_BOTH` | The fan is swinging both horizontal and vertical. | - -### Supported features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Name | Description | -| ---------------------------------- | ------------------------------------------------------------------------------------------- | -| `SUPPORT_TARGET_TEMPERATURE` | The device supports a target temperature. | -| `SUPPORT_TARGET_TEMPERATURE_RANGE` | The device supports a ranged target temperature. Used for HVAC modes `heat_cool` and `auto` | -| `SUPPORT_TARGET_HUMIDITY` | The device supports a target humidity. | -| `SUPPORT_FAN_MODE` | The device supports fan modes. | -| `SUPPORT_PRESET_MODE` | The device supports presets. | -| `SUPPORT_SWING_MODE` | The device supports swing modes. | -| `SUPPORT_AUX_HEAT` | The device supports auxiliary heaters. | - -## Methods - -### Set hvac mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_hvac_mode(self, hvac_mode): - """Set new target hvac mode.""" - - async def async_set_hvac_mode(self, hvac_mode): - """Set new target hvac mode.""" -``` - -### Set preset mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_preset_mode(self, preset_mode): - """Set new target preset mode.""" - - async def async_set_preset_mode(self, preset_mode): - """Set new target preset mode.""" -``` - -### Set fan mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_fan_mode(self, fan_mode): - """Set new target fan mode.""" - - async def async_set_fan_mode(self, fan_mode): - """Set new target fan mode.""" -``` - -### Set humidity - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_humidity(self, humidity): - """Set new target humidity.""" - - async def async_set_humidity(self, humidity): - """Set new target humidity.""" -``` - -### Set swing mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_swing_mode(self, swing_mode): - """Set new target swing operation.""" - - async def async_set_swing_mode(self, swing_mode): - """Set new target swing operation.""" -``` - -### Set temperature - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_temperature(self, **kwargs): - """Set new target temperature.""" - - async def async_set_temperature(self, **kwargs): - """Set new target temperature.""" -``` - -### Control auxiliary heater - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_aux_heat_on(self): - """Turn auxiliary heater on.""" - - async def async_turn_aux_heat_on(self): - """Turn auxiliary heater on.""" - - # Implement one of these methods. - - def turn_aux_heat_off(self): - """Turn auxiliary heater off.""" - - async def async_turn_aux_heat_off(self): - """Turn auxiliary heater off.""" -``` diff --git a/website/versioned_docs/version-0.101.0/hassio_addon_config.md b/website/versioned_docs/version-0.101.0/hassio_addon_config.md deleted file mode 100644 index 20e3c39d..00000000 --- a/website/versioned_docs/version-0.101.0/hassio_addon_config.md +++ /dev/null @@ -1,232 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.101.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - apparmor.txt - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -All our Images have also [bashio][bashio] installed. It contains a set of commonly used operations and can be used to be included in add-ons to reduce code duplication across add-ons and therefore making it easier to develop and maintain add-ons. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use bashio or `jq` inside your shell script to parse this data. - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -[bashio]: https://github.com/hassio-addons/bashio - -## Add-on Docker file - -All add-ons are based on latest Alpine Linux. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | yes | List of supported arch: `armhf`, `armv7`, `aarch64`, `amd64`, `i386`. -| machine | list | no | Default it support any machine type. You can select that this add-on run only on specific machines. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. If host-port is `null`, the mapping is disabled. -| ports_description | dict | no | Network ports description mapping. Format is `"container-port/type": "description of this port"`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| udev | bool | no | Default False. Set this True, if your container run a own udev process. -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| homeassistant | string | no | Pin a minimum required Home Assistant version for such Add-on. Value is a version string like `0.91.2`. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| kernel_modules | bool | no | Map host kernel modules and config into add-on (readonly). -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| auth_api | bool | no | Allow access to Home Assistent user backend. -| ingress | bool | no | Enable the ingress feature for the Add-on -| ingress_port | integer | no | Default `8099`. For Add-ons they run on host network, you can use `0` and read the port later on API. -| ingress_entry | string | no | Modify the URL entry point from `/`. -| panel_icon | string | no | Default: mdi:puzzle. MDI icon for the menu panel integration. -| panel_title | string | no | Default add-on name, but can Modify with this options. -| panel_admin | bool | no | Default True. Make menu entry only available with admin privileged. -| snapshot_exlude | list | no | List of file/path with glob support they are excluded from snapshots. - - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str / str(min,) / str(,max) / str(min,max) -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) -- list(val1|val2|...) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. - -We provide a set of [Base-Images][hassio-base] which should cover a lot of needs. If you don't want use the Alpine based version or need a specific Image tag, feel free to pin this requirements for you build with `build_from` option. - -[hassio-base]: https://github.com/home-assistant/hassio-base diff --git a/website/versioned_docs/version-0.101.0/integration_quality_scale_index.md b/website/versioned_docs/version-0.101.0/integration_quality_scale_index.md deleted file mode 100644 index 8dac818d..00000000 --- a/website/versioned_docs/version-0.101.0/integration_quality_scale_index.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Integration Quality Scale -id: version-0.101.0-integration_quality_scale_index -original_id: integration_quality_scale_index ---- - -The Integration Quality Scale scores each integration based on the code quality and user experience. Each level of the quality scale consists of a list of requirements. If an integration matches all requirements, it's considered to have reached that level. - -> Suggestions for changes can be done by creating an issue in the [architecture repo](https://github.com/home-assistant/architecture/issues/). - -# No score - -This integration passes the bare minimum requirements to become part of the index. - - - Satisfy all requirements for [creating components](creating_component_code_review.md) and [creating platforms](creating_platform_code_review.md). - - Configurable via `configuration.yaml` - -# Silver 🥈 - -This integration is able to cope when things go wrong. It will not print any exceptions nor will it fill the log with retry attempts. - -- Connection/configuration is handled via a component. -- Set an appropriate `SCAN_INTERVAL` (if a polling integration) -- Raise `PlatformNotReady` if unable to connect during platform setup (if appropriate) -- Handles expiration of auth credentials. Refresh if possible or print correct error and fail setup. If based on a config entry, should trigger a new config entry flow to re-authorize. -- Handles internet unavailable. Log a warning once when unavailable, log once when reconnected. -- Handles device/service unavailable. Log a warning once when unavailable, log once when reconnected. -- Set `available` property to `False` if appropriate ([docs](entity_index.md#generic-properties)) -- Entities have unique ID (if available) ([docs](entity_registry_index.md#unique-id-requirements)) - -# Gold 🥇 - -This is a solid integration that is able to survive poor conditions and can be configured via the user interface. - -- Configurable via config entries. - - Don't allow configuring already configured device/service (example: no 2 entries for same hub) - - Tests for the config flow - - Discoverable (if available) -- Entities have device info (if available) ([docs](device_registry_index.md#defining-devices)) -- States are translated in the frontend (text-based sensors only, [docs](internationalization_index.md)) -- Tests for reading data from/controlling the integration ([docs](development_testing.md)) -- Has a code owner ([docs](creating_integration_manifest.md#code-owners)) - -# Platinum 🏆 - -Best of the best. The integration is completely async, meaning it's super fast. Integrations that reach platinum level will require approval by the code owner for each PR. - -- Set appropriate `PARALLEL_UPDATES` constant -- Support config entry unloading (called when config entry is removed) -- Integration + dependency are async -- Uses aiohttp and allows passing in websession (if making HTTP requests) - -# Internal 🏠 - -Integrations which are part of Home Assistant are not rated but marked as **internal**. - diff --git a/website/versioned_docs/version-0.101.0/lovelace_custom_card.md b/website/versioned_docs/version-0.101.0/lovelace_custom_card.md deleted file mode 100644 index b76bcf77..00000000 --- a/website/versioned_docs/version-0.101.0/lovelace_custom_card.md +++ /dev/null @@ -1,243 +0,0 @@ ---- -title: Lovelace: Custom Cards -id: version-0.101.0-lovelace_custom_card -original_id: lovelace_custom_card ---- - -[Lovelace](https://www.home-assistant.io/lovelace/) is our new approach to defining your user interface for Home Assistant. We offer a lot of built-in cards, but you're not just limited to the ones that we decided to include in the Lovelace UI. You can build and use your own! - -## API - -You define your custom card as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). It's up to you to decide how to render your DOM inside your element. You can use Polymer, Angular, Preact or any other popular framework (except for React – [more info on React here](https://custom-elements-everywhere.com/#react)). - -```js -const element = document.createElement('some-custom-card'); -``` - -Home Assistant will call `setConfig(config)` when the configuration changes (rare). If you throw an exception if the configuration is invalid, Lovelace will render an error card to notify the user. - -```js -try { - element.setConfig(config); -} catch (err) { - showErrorCard(err.message, config); -} -``` - -Home Assistant will set the `hass` property when the state of Home Assistant changes (frequent). Whenever the state changes, the component will have to update itself to represent the latest state. - -```js -element.hass = hass; -``` - -Your card can define a `getCardSize` method that returns the size of your card as a number. A height of 1 is equivalent to 50 pixels. This will help Home Assistant distribute the cards evenly over the columns. A card size of `1` will be assumed if the method is not defined. - -```js -if ('getCardSize' in element) { - return element.getCardSize(); -} else { - return 1; -} -``` - -## Defining your card - -Create a new file in your Home Assistant config dir as `/www/content-card-example.js` and put in the following contents: - -```js -class ContentCardExample extends HTMLElement { - set hass(hass) { - if (!this.content) { - const card = document.createElement('ha-card'); - card.header = 'Example card'; - this.content = document.createElement('div'); - this.content.style.padding = '0 16px 16px'; - card.appendChild(this.content); - this.appendChild(card); - } - - const entityId = this.config.entity; - const state = hass.states[entityId]; - const stateStr = state ? state.state : 'unavailable'; - - this.content.innerHTML = ` - The state of ${entityId} is ${stateStr}! -

- - `; - } - - setConfig(config) { - if (!config.entity) { - throw new Error('You need to define an entity'); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return 3; - } -} - -customElements.define('content-card-example', ContentCardExample); -``` - -## Referencing your new card - -In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `/www` directory, it will be accessible in your browser via the url `/local/` (if you have recently added the www folder you will need to re-start home assistant for files to be picked up). - -```yaml -# Example Lovelace configuration -resources: - - url: /local/content-card-example.js - type: js -views: -- name: Example - cards: - - type: "custom:content-card-example" - entity: input_boolean.switch_tv -``` - -## Advanced example - -Resources to load in Lovelace can be imported as a JS script, an HTML import or as a JS module import. Below is an example of a custom card using JS modules that does all the fancy things. - -![Screenshot of the wired card](/img/en/frontend/lovelace-ui-custom-card-screenshot.png) - -Create a new file in your Home Assistant config dir as `/www/wired-cards.js` and put in the following contents: - -```js -import "https://unpkg.com/wired-card@0.8.1/wired-card.js?module"; -import "https://unpkg.com/wired-toggle@0.8.0/wired-toggle.js?module"; -import { - LitElement, - html, - css -} from "https://unpkg.com/lit-element@2.0.1/lit-element.js?module"; - -function loadCSS(url) { - const link = document.createElement("link"); - link.type = "text/css"; - link.rel = "stylesheet"; - link.href = url; - document.head.appendChild(link); -} - -loadCSS("https://fonts.googleapis.com/css?family=Gloria+Hallelujah"); - -class WiredToggleCard extends LitElement { - static get properties() { - return { - hass: {}, - config: {} - }; - } - - render() { - return html` - - ${this.config.entities.map(ent => { - const stateObj = this.hass.states[ent]; - return stateObj - ? html` -
- ${stateObj.attributes.friendly_name} - -
- ` - : html` -
Entity ${ent} not found.
- `; - })} -
- `; - } - - setConfig(config) { - if (!config.entities) { - throw new Error("You need to define entities"); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return this.config.entities.length + 1; - } - - _toggle(state) { - this.hass.callService("homeassistant", "toggle", { - entity_id: state.entity_id - }); - } - - static get styles() { - return css` - :host { - font-family: "Gloria Hallelujah", cursive; - } - wired-card { - background-color: white; - padding: 16px; - display: block; - font-size: 18px; - } - .state { - display: flex; - justify-content: space-between; - padding: 8px; - align-items: center; - } - .not-found { - background-color: yellow; - font-family: sans-serif; - font-size: 14px; - padding: 8px; - } - wired-toggle { - margin-left: 8px; - } - `; - } -} -customElements.define("wired-toggle-card", WiredToggleCard); -``` - -And for your configuration: - -```yaml -# Example Lovelace configuration -resources: - - url: /local/wired-cards.js - type: module -views: -- name: Example - cards: - - type: "custom:wired-toggle-card" - entities: - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_livingroom - - input_boolean.switch_tv -``` - -## Recommended Design Elements -We are currently migrating from using Paper Elements to MWC (Material Web Component) Elements. - -If an element exists in the below repository for MWC. We recommended using it. -- [MWC (Material Web Components)](https://material-components.github.io/material-components-web-components/demos/index.html) - -If an element does not exist in MWC, we default to using Paper Elements. -- [Paper Elements](https://www.webcomponents.org/collection/PolymerElements/paper-elements) - -## Advanced Resources -Community Maintained Boilerplate Card - Advanced Template (Typescript, Rollup, Linting, etc.) -- [Boilerplate Card](https://github.com/custom-cards/boilerplate-card) - -Developer Documentation for [HACS](https://hacs.netlify.com/) (Home Assistant Community Store). -- [HACS Plugin Docs](https://hacs.netlify.com/developer/plugin/) diff --git a/website/versioned_docs/version-0.102.0/app_integration_setup.md b/website/versioned_docs/version-0.102.0/app_integration_setup.md deleted file mode 100644 index e00cffc8..00000000 --- a/website/versioned_docs/version-0.102.0/app_integration_setup.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Connecting to an instance -id: version-0.102.0-app_integration_setup -original_id: app_integration_setup ---- - -When a user first opens the app, they will need to connect to their local instance to authenticate and register the device. - -## Authenticating the user - -The local instance can be discovered if Home Assistant has the [zeroconf component] configured by searching for `_home-assistant._tcp.local.`. If not configured, the user will need to be asked for the local address of their instance. - -When the address of the instance is known, the app will ask the user to authenticate via [OAuth2 with Home Assistant]. Home Assistant uses IndieAuth, which means that to be able to redirect to a url that triggers your app, you need to take some extra steps. Make sure to read the last paragraph of the "Clients" section thoroughly. - -[zeroconf component]: https://www.home-assistant.io/components/zeroconf -[OAuth2 with Home Assistant]: auth_api.md - -## Registering the device - -_This requires Home Assistant 0.90 or later._ - -Home Assistant has a `mobile_app` component that allows applications to register themselves and interact with the instance. This is a generic component to handle most common mobile application tasks. This component is extendable with custom interactions if your app needs more types of interactions than are offered by this component. - -Once you have tokens to authenticate as a user, it's time to register the app with the mobile app component in Home Assistant. - -### Getting Ready - -First, you must ensure that the `mobile_app` component is loaded. There are two ways to do this: - -- You can publish a Zeroconf/Bonjour record `_hass-mobile-app._tcp.local.` to trigger the automatic load of the `mobile_app` component. You should wait at least 60 seconds after publishing the record before continuing. -- You can ask the user to add `mobile_app` to their configuration.yaml and restart Home Assistant. If the user already has `default_config` in their configuration, then `mobile_app` will have been already loaded. - -You can confirm the `mobile_app` component has been loaded by checking the `components` array of the [`/api/config` REST API call](external_api_rest.md#get-api-config). If you continue to device registration and receive a 404 status code, then it most likely hasn't been loaded yet. - -### Registering the device - -To register the device, make an authenticated POST request to `/api/mobile_app/registrations`. [More info on making authenticated requests.](auth_api.md#making-authenticated-requests) - -Example payload to send to the registration endpoint: - -```json -{ - "app_id": "awesome_home", - "app_name": "Awesome Home", - "app_version": "1.2.0", - "device_name": "Robbies iPhone", - "manufacturer": "Apple, Inc.", - "model": "iPhone X", - "os_name": "iOS", - "os_version": "iOS 10.12", - "supports_encryption": true, - "app_data": { - "push_notification_key": "abcdef", - } -} -``` - -| Key | Required | Type | Description | -| --- | -------- | ---- | ----------- | -| `app_id` | V | string | A unique identifier for this app. -| `app_name` | V | string | Name of the mobile app. -| `app_version` | V | string | Version of the mobile app. -| `device_name` | V | string | Name of the device running the app. -| `manufacturer` | V | string | The manufacturer of the device running the app. -| `model` | V | string | The model of the device running the app. -| `os_name` | V | string | The name of the OS running the app. -| `os_version` | V | string | The OS version of the device running the app. -| `supports_encryption` | V | bool | If the app supports encryption. See also the [encryption section](#encryption). -| `app_data` | | Dict | App data can be used if the app has a supporting component that extends `mobile_app` functionality. - -When you get a 200 response, the mobile app is registered with Home Assistant. The response is a JSON document and will contain the URLs on how to interact with the Home Assistant instance. You should permanently store this information. - -```json -{ - "cloudhook_url": "https://hooks.nabu.casa/randomlongstring123", - "remote_ui_url": "https://randomlongstring123.ui.nabu.casa", - "secret": "qwerty", - "webhook_id": "abcdefgh" -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `cloudhook_url` | string | The cloudhook URL provided by Home Assistant Cloud. Only will be provided if user is actively subscribed to Nabu Casa. -| `remote_ui_url` | string | The remote UI URL provided by Home Assistant Cloud. Only will be provided if user is actively subscribed to Nabu Casa. -| `secret` | string | The secret to use for encrypted communication. Will only be included if encryption is supported by both the app and the Home Assistant instance. [More info](app_integration_sending_data.md#implementing-encryption). -| `webhook_id` | string | The webhook ID that can be used to send data back. diff --git a/website/versioned_docs/version-0.102.0/config_entries_config_flow_handler.md b/website/versioned_docs/version-0.102.0/config_entries_config_flow_handler.md deleted file mode 100644 index e11d6351..00000000 --- a/website/versioned_docs/version-0.102.0/config_entries_config_flow_handler.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Integration Configuration -sidebar_label: Configuration -id: version-0.102.0-config_entries_config_flow_handler -original_id: config_entries_config_flow_handler ---- - -Integrations can be set up via the user interface by adding support for a config flow to create a config entry. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like Hass.io). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -## Updating the manifest - -You need to update your integrations manifest to inform Home Assistant that your integration has a config flow. This is done by adding `config_flow: true` to your manifest ([docs](creating_integration_manifest.md#config-flow)). - -## Defining your config flow - -Config entries uses the [data flow entry framework](data_entry_flow_index.md) to define their config flows. The config flow needs to be defined in the file `config_flow.py` in your integration folder, extend `homeassistant.config_entries.ConfigFlow` and pass a `domain` key as part of inheriting `ConfigFlow`. - -```python -from homeassistant import config_entries -from .const import DOMAIN - -class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): -``` - -## Defining steps - -Your config flow will need to define steps of your configuration flow. The docs for [Data Entry Flow](data_entry_flow_index.md) describe the different return values of a step. Here is an example on how to define the `user` step. - -```python -class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): - - async def async_step_user(self, info): - if info is not None: - # process info - - return self.async_show_form( - step_id='user', - data_schema=vol.Schema({ - vol.Required('password'): str - }) - ) -``` - -There are a few step names reserved for system use: - -| Step name | Description | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `user` | Invoked when a user initiates a flow via the user interface. | -| `zeroconf` | Invoked if your integration has been discovered via Zeroconf/mDNS as specified [using `zeroconf` in the manifest](creating_integration_manifest.md#zeroconf). | -| `homekit` | Invoked if your integration has been discovered via HomeKit as specified [using `homekit` in the manifest](creating_integration_manifest.md#homekit). | -| `ssdp` | Invoked if your integration has been discovered via SSDP/uPnP as specified [using `ssdp` in the manifest](creating_integration_manifest.md#ssdp). | -| `discovery` | _DEPRECATED_ Invoked if your integration has been discovered by the discovery integration. | - -## Discovery steps - -When an integration is discovered, their respective discovery step is invoked with the discovery information. The step will have to check the following things: - -- Make sure there are no other instances of this config flow in progress of setting up the discovered device. This can happen if there are multiple ways of discovering that a device is on the network. -- Make sure that the device is not already set up. -- Invoking a discovery step should never result in a finished flow and a config entry. Always confirm with the user. - -## Discoverable integrations that require no authentication - -If your integration is discoverable without requiring any authentication, you'll be able to use the Discoverable Flow that is built-in. This flow offers the following features: - -- Detect if devices/services can be discovered on the network before finishing the config flow. -- Support all manifest-based discovery protocols. -- Limit to only 1 config entry. It is up to the config entry to discover all available devices. - -To get started, run `python3 -m script.scaffold config_flow_discovery` and follow the instructions. This will create all the boilerplate necessary to configure your integration using discovery. - -## Configuration via OAuth2 - -Home Assistant has built-in support for integrations that offer account linking using [the OAuth2 authorization framework](https://tools.ietf.org/html/rfc6749). To be able to leverage this, you will need to structure your Python API library in a way that allows Home Assistant to be responsible for refreshing tokens. See our [API library guide](api_lib_index.md) on how to do this. - -The built-in OAuth2 support works out of the box with locally configured client ID / secret and with the Home Assistant Cloud Account Linking service. This service allows users to link their account with a centrally managed client ID/secret. If you want your integration to be part of this service, reach out to us at [hello@home-assistant.io](mailto:hello@home-assistant.io). - -To get started, run `python3 -m script.scaffold config_flow_oauth2` and follow the instructions. This will create all the boilerplate necessary to configure your integration using OAuth2. - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` - -When the translations are merged into Home Assistant, they will be automatically uploaded to [Lokalise](https://lokalise.co/) where the translation team will help to translate them in other languages. [More info on translating Home Assistant.](internationalization_translation.md) diff --git a/website/versioned_docs/version-0.102.0/development_testing.md b/website/versioned_docs/version-0.102.0/development_testing.md deleted file mode 100644 index 5a458dae..00000000 --- a/website/versioned_docs/version-0.102.0/development_testing.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Testing your code -id: version-0.102.0-development_testing -original_id: development_testing ---- - -As it states in the [Style guidelines section](development_guidelines.md) all code is checked to verify the following: - -- All the unit tests pass -- All code passes the checks from the linting tools - -Local testing is done using [Tox](https://tox.readthedocs.io), which has been installed as part of running `script/setup` in the [virtual environment](development_environment.md). To start the tests, activate the virtual environment and simply run the command: - -```bash -$ tox -``` - -It might be required that you install additional packages depending on your distribution/operating system: - -- Fedora: `sudo dnf -y install systemd-devel gcc-c++` -- Ubuntu: `sudo spt-get install libudev-dev` - -**Important:** Run `tox` before you create your pull request to avoid annoying fixes. - -Running `tox` will run unit tests against the locally available Python releases, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one `tox` target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py38` runs unit tests only on Python 3.8. - -`tox` uses virtual environments under the hood to create isolated testing environments. The `tox` virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell `tox` to recreate the virtual environments. - -macOS users may see an `Error creating virtualenv` when runnng `tox`. If this occurs, install the [tox-venv](https://pypi.org/project/tox-venv/) package using the command `pip install tox-venv` and try again. - -### Adding new dependencies to test environment - -If you are working on tests for an integeration and you need the dependencies available inside the `tox` environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments. - -### Running single tests using `tox` - -You can pass arguments via `tox` to `py.test` to be able to run single test suites or test files. Replace `py38` with the Python version that you use. - -```bash -# Stop after the first test fails -$ tox -e py38 -- tests/test_core.py -x -# Run test with specified name -$ tox -e py38 -- tests/test_core.py -k test_split_entity_id -# Fail a test after it runs for 2 seconds -$ tox -e py38 -- tests/test_core.py --timeout 2 -# Show the 10 slowest tests -$ tox -e py38 -- tests/test_core.py --duration=10 -``` - -### Testing outside of Tox - -Running `tox` will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without `tox`, you'll need to install the test dependencies into your Python environment: - -```bash -$ pip3 install -r requirements_test_all.txt -c homeassistant/package_constraints.txt -``` - -Now that you have all test dependencies installed, you can run tests on individual files: - -```bash -$ flake8 homeassistant/core.py -$ pylint homeassistant/core.py -$ pydocstyle homeassistant/core.py -$ py.test tests/test_core.py -``` - -You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script: - -```bash -$ script/lint -``` - -### Preventing linter errors - -Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them! - -```bash -$ pip3 install flake8 flake8-docstrings -$ flake8 --install-hook=git -``` - -The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8. - -### Notes on PyLint and PEP8 validation - -If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member. diff --git a/website/versioned_docs/version-0.102.0/entity_index.md b/website/versioned_docs/version-0.102.0/entity_index.md deleted file mode 100644 index 97c84ad4..00000000 --- a/website/versioned_docs/version-0.102.0/entity_index.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Entity -sidebar_label: Introduction -id: version-0.102.0-entity_index -original_id: entity_index ---- - -Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating. - -Below is an example switch entity that keeps track of their state in memory. - -```python -from homeassistant.components.switch import SwitchDevice - -class MySwitch(SwitchDevice): - - def __init__(self): - self._is_on = False - - @property - def name(self): - """Name of the device.""" - return 'My Switch' - - @property - def is_on(self): - """If the switch is currently on or off.""" - return self._is_on - - def turn_on(self, **kwargs): - """Turn the switch on.""" - self._is_on = True - - def turn_off(self, **kwargs): - """Turn the switch off.""" - self._is_on = False -``` - -That's all there is to it to build a switch entity! Continue reading to learn more or check out the [video tutorial](https://youtu.be/Cfasc9EgbMU?t=737). - -## Updating the entity - -An entity represents a device. There are various strategies to keep your entity in sync with the state of the device, the most popular one being polling. - -### Polling - -With polling, Home Assistant will ask the entity from time to time (depending on the update interval of the component) to fetch the latest state. Home Assistant will poll an entity when the `should_poll` property returns `True` (the default value). You can either implement your update logic using `update()` or the async method `async_update()`. This method should fetch the latest state from the device and store it in an instance variable for the properties to return it. - -### Subscribing to updates - -When you subscribe to updates, your code is responsible for letting Home Assistant know that an update is available. Make sure you have the `should_poll` property return `False`. - -Whenever you receive new state from your subscription, you can tell Home Assistant that an update is available by calling `schedule_update_ha_state()` or async callback `async_schedule_update_ha_state()`. Pass in the boolean `True` to the method if you want Home Assistant to call your update method before writing the update to Home Assistant. - -## Generic properties - -The entity base class has a few properties that are common among all entities in Home Assistant. These can be added to any entity regardless of the type. All these properties are optional and don't need to be implemented. - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| assumed_state | boolean | `False` | Return `True` if the state is based on our assumption instead of reading it from the device. -| available | boolean | `True` | Indicate if Home Assistant is able to read the state and control the underlying device. -| device_state_attributes | dict | `None` | Extra information to store in the state machine. It needs to be information that further explains the state, it should not be static information like firmware version. See [below](entity_index.md#standard-attributes) for details of standard attributes. -| entity_picture | URL | `None` | Url of a picture to show for the entity. -| name | string | `None` | Name of the entity -| should_poll | boolean | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](#methods). -| unique_id | string | `None` | A unique identifier for this entity. Needs to be unique within a platform (ie `light.hue`). Should not be configurable by the user or be changeable. [Learn more.](entity_registry_index.md#unique-id-requirements) - -## Advanced properties - -The following properties are also available on entities. However, they are for advanced use only and should be used with caution. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| force_update | boolean | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine. -| hidden | boolean | `False` | Indicate if the entity should not be shown on the frontend. -| icon | icon | `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all devices. -| entity_registry_enabled_default | boolean | `True` | Indicate if the entity should be enabled or disabled when it is first added to the entity registry. - -## System properties - -The following properties are used and controlled by Home Assistant, and should not be overridden by integrations. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| enabled | boolean | `True` | Indicate if entity is enabled in the entity registry. It also returns `True` if the platform doesn't support the entity registry. Disabled entities will not be added to Home Assistant. - -## Standard attributes - -The following `device_state_attributes` are considered standard and should follow the convention below. The constant should be imported from `homeassistant/const.py`. - -| Name | Type | Unit | Constant | Description -| ---- | ---- | ---- | -------- | ----------- -| battery_charging | boolean | N/A | `ATTR_BATTERY_CHARGING` | Battery charging status of the entity, shown as a boolean `true` or `false`. If charging is not supported, then this attribute should not be created. -| battery_level | integer | % | `ATTR_BATTERY_LEVEL` | Battery level of the entity, shown as an integer percentage between 0-100. - -## Lifecycle hooks - -Use these lifecycle hooks to execute code when certain events happen to the entity. All lifecycle hooks are async methods. - -### `async_added_to_hass()` - -Called when an entity has their entity_id and hass object assigned, before it is written to the state machine for the first time. Example uses: restore the state, subscribe to updates or set callback/dispatch function/listener. - -### `async_will_remove_from_hass()` - -Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates. - -## Changing the entity model - -If you want to add a new feature to an entity or any of its subtypes (light, switch, etc), you will need to propose it first in our [architecture repo](https://github.com/home-assistant/architecture/issues). Only additions will be considered that are common features among various vendors. diff --git a/website/versioned_docs/version-0.102.0/frontend_external_auth.md b/website/versioned_docs/version-0.102.0/frontend_external_auth.md deleted file mode 100644 index dade3ed6..00000000 --- a/website/versioned_docs/version-0.102.0/frontend_external_auth.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: External Authentication -id: version-0.102.0-frontend_external_auth -original_id: frontend_external_auth ---- - -By default, the frontend will take care of its own authentication tokens. If none found, it will redirect the user to the login page and it will take care that the token is up to date. - -If you want to embed the Home Assistant frontend in an external app, you will want to store the authentication inside the app but make it available to the frontend. To support this, Home Assistant exposes an external authentication API. - -To activate this API, load the frontend with `?external_auth=1` appended to the URL. If this is passed in, Home Assistant will expect either `window.externalApp` (for Android) or `window.webkit.messageHandlers` (for iOS) to be defined containing the methods described below. - -## Get Access Token - -_This API has been introduced in Home Assistant 0.78._ - -When the frontend loads, it will request an access token from the external authentication. It does so by calling one of the following methods with an options object. The options object defines the callback method to be called with the response. - -```js -window.externalApp.getExternalAuth({ - callback: 'externalAuthSetToken' -}); -// or -window.webkit.messageHandlers.getExternalAuth.postMessage({ - callback: 'externalAuthSetToken' -}); -``` - -The response should contain a boolean if it was successful and an object containing an access token and the number of seconds that it will remain valid. Pass the response to the function defined in the options object. - -```js -// To be called by external app -window.externalAuthSetToken(true, { - "access_token": "qwere", - "expires_in": 1800 -}); - -// If unable to get new access token -window.externalAuthSetToken(false); -``` - -The frontend will call this method when the page first loads and whenever it needs a valid token but the previous received token has expired. - -## Revoke Token - -_This API has been introduced in Home Assistant 0.78._ - -When the user presses the logout button on the profile page, the external app will have to [revoke the refresh token](auth_api.md#revoking-a-refresh-token), and log the user out. - -```js -window.externalApp.revokeExternalAuth({ - callback: 'externalAuthRevokeToken' -}); -// or -window.webkit.messageHandlers.revokeExternalAuth.postMessage({ - callback: 'externalAuthRevokeToken' -}); -``` - -When done, the external app has to call the function defined in the options object. - -```js -// To be called by external app -window.externalAuthRevokeToken(true); - -// If unable to logout -window.externalAuthRevokeToken(false); -``` diff --git a/website/versioned_docs/version-0.102.0/hassio_addon_communication.md b/website/versioned_docs/version-0.102.0/hassio_addon_communication.md deleted file mode 100644 index 15a97cba..00000000 --- a/website/versioned_docs/version-0.102.0/hassio_addon_communication.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Add-On Communication -id: version-0.102.0-hassio_addon_communication -original_id: hassio_addon_communication ---- - -There are different ways for communication between add-ons inside Hass.io. - -## Network - -We use an internal network that's allowed to communicate with every add-on, including to/from Home Assistant, by using its name or alias. Only add-ons that run on the host network are limited in that they can talk with all internal add-ons by their name, but all other add-ons can't address these add-ons by name. However, using an alias works for both! - -Names/aliases are used for communication inside Hass.io. -The name is generated using the following format: `{REPO}_{SLUG}`, e.g., `local_xy` or `3283fh_myaddon`. In this example, `{SLUG}` is defined in an add-on's `config.json` file. You can use this name as the DNS name also, but you need replace any `_` with `-` to have a valid hostname. If an add-on is installed locally, `{REPO}` will be `local`. If the add-on is installed from a Github repository, `{REPO}` is a hashed identifier generated from the GitHub repository's URL (ex: https://github.com/xy/my_hassio_addons). See [here](https://github.com/home-assistant/hassio/blob/587047f9d648b8491dc8eef17dc6777f81938bfd/hassio/addons/utils.py#L17) to understand how this identifier is generated. Note that this identifier is required in certain service calls that use the [Hass.io add-on API][hassio-addon-api]. You can view the repository identifiers for all currently-installed add-ons via a GET request to the hassio API `addons` endpoint. - -Use `hassio` for communication with the internal API. - -## Home Assistant - -An add-on can talk to the [Home Assistant API][hass-api] using the internal proxy. This makes it very easy to communicate with the API without knowing the password, port or any other information about the Home Assistant instance. Using this URL: `http://hassio/homeassistant/api` ensures that internal communication is redirected to the right place. The next step is to add `homeassistant_api: true` to the `config.json` file and read the environment variable `HASSIO_TOKEN`. Use this as the Home Assistant [bearer token](https://developers.home-assistant.io/docs/en/auth_api.html#making-authenticated-requests) when making requests. - -For example `curl -X GET -H "Authorization: Bearer ${HASSIO_TOKEN}" -H "Content-Type: application/json" http://hassio/homeassistant/api/discovery_info` - -There is also a proxy for the [Home Assistant Websocket API][hass-websocket] that works like the API proxy above and requires `HASSIO_TOKEN` as the password. Use this URL: `http://hassio/homeassistant/websocket`. - -It is also possible to talk directly to the Home Assistant instance, which is named `homeassistant`, over the internal network. However, you'll need to know the configuration that is used by the running instance. - -We have several services for Hass.io inside Home Assistant to run tasks. Send data over STDIN to an add-on to use the `hassio.addon_stdin` service. - -## Hass.io API - -To enable calls to the [Hass.io API][hassio-api], add `hassio_api: true` to the `config.json` file and read the environment variable `HASSIO_TOKEN`. Now you can use the API over the URL: `http://hassio/`. Use the `HASSIO_TOKEN` with header `X-HASSIO-KEY`. You may also need to change the Hass.io API role to `hassio_role: default`. - -Add-ons can call some API commands without needing to set `hassio_api: true`: -- `/homeassistant/api` -- `/homeassistant/api/stream` -- `/homeassistant/websocket` -- `/addons/self/*` -- `/services*` -- `/discovery*` -- `/info` - -***Note:*** For Home Assistant API access requirements, see above. - -[hass-api]: https://www.home-assistant.io/developers/rest_api/ -[hass-websocket]: https://www.home-assistant.io/developers/websocket_api/ -[hassio-api]: https://github.com/home-assistant/hassio/blob/master/API.md -[hassio-addon-api]: https://github.com/home-assistant/hassio/blob/dev/API.md#restful-for-api-addons diff --git a/website/versioned_docs/version-0.102.0/lovelace_custom_card.md b/website/versioned_docs/version-0.102.0/lovelace_custom_card.md deleted file mode 100644 index 0ef4f4e5..00000000 --- a/website/versioned_docs/version-0.102.0/lovelace_custom_card.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -title: Lovelace: Custom Cards -id: version-0.102.0-lovelace_custom_card -original_id: lovelace_custom_card ---- - -[Lovelace](https://www.home-assistant.io/lovelace/) is our new approach to defining your user interface for Home Assistant. We offer a lot of built-in cards, but you're not just limited to the ones that we decided to include in the Lovelace UI. You can build and use your own! - -## API - -You define your custom card as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). It's up to you to decide how to render your DOM inside your element. You can use Polymer, Angular, Preact or any other popular framework (except for React – [more info on React here](https://custom-elements-everywhere.com/#react)). - -```js -const element = document.createElement('some-custom-card'); -``` - -Home Assistant will call `setConfig(config)` when the configuration changes (rare). If you throw an exception if the configuration is invalid, Lovelace will render an error card to notify the user. - -```js -try { - element.setConfig(config); -} catch (err) { - showErrorCard(err.message, config); -} -``` - -Home Assistant will set the `hass` property when the state of Home Assistant changes (frequent). Whenever the state changes, the component will have to update itself to represent the latest state. - -```js -element.hass = hass; -``` - -Your card can define a `getCardSize` method that returns the size of your card as a number. A height of 1 is equivalent to 50 pixels. This will help Home Assistant distribute the cards evenly over the columns. A card size of `1` will be assumed if the method is not defined. - -```js -if ('getCardSize' in element) { - return element.getCardSize(); -} else { - return 1; -} -``` - -## Defining your card - -Create a new file in your Home Assistant config dir as `/www/content-card-example.js` and put in the following contents: - -```js -class ContentCardExample extends HTMLElement { - set hass(hass) { - if (!this.content) { - const card = document.createElement('ha-card'); - card.header = 'Example card'; - this.content = document.createElement('div'); - this.content.style.padding = '0 16px 16px'; - card.appendChild(this.content); - this.appendChild(card); - } - - const entityId = this.config.entity; - const state = hass.states[entityId]; - const stateStr = state ? state.state : 'unavailable'; - - this.content.innerHTML = ` - The state of ${entityId} is ${stateStr}! -

- - `; - } - - setConfig(config) { - if (!config.entity) { - throw new Error('You need to define an entity'); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return 3; - } -} - -customElements.define('content-card-example', ContentCardExample); -``` - -## Referencing your new card - -In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `/www` directory, it will be accessible in your browser via the url `/local/` (if you have recently added the www folder you will need to re-start home assistant for files to be picked up). - -```yaml -# Example Lovelace configuration -resources: - - url: /local/content-card-example.js - type: js -views: -- name: Example - cards: - - type: "custom:content-card-example" - entity: input_boolean.switch_tv -``` - -## Advanced example - -Resources to load in Lovelace can be imported as a JS script, an HTML import or as a JS module import. Below is an example of a custom card using JS modules that does all the fancy things. - -![Screenshot of the wired card](/img/en/frontend/lovelace-ui-custom-card-screenshot.png) - -Create a new file in your Home Assistant config dir as `/www/wired-cards.js` and put in the following contents: - -```js -import "https://unpkg.com/wired-card@0.8.1/wired-card.js?module"; -import "https://unpkg.com/wired-toggle@0.8.0/wired-toggle.js?module"; -import { - LitElement, - html, - css -} from "https://unpkg.com/lit-element@2.0.1/lit-element.js?module"; - -function loadCSS(url) { - const link = document.createElement("link"); - link.type = "text/css"; - link.rel = "stylesheet"; - link.href = url; - document.head.appendChild(link); -} - -loadCSS("https://fonts.googleapis.com/css?family=Gloria+Hallelujah"); - -class WiredToggleCard extends LitElement { - static get properties() { - return { - hass: {}, - config: {} - }; - } - - render() { - return html` - - ${this.config.entities.map(ent => { - const stateObj = this.hass.states[ent]; - return stateObj - ? html` -
- ${stateObj.attributes.friendly_name} - -
- ` - : html` -
Entity ${ent} not found.
- `; - })} -
- `; - } - - setConfig(config) { - if (!config.entities) { - throw new Error("You need to define entities"); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return this.config.entities.length + 1; - } - - _toggle(state) { - this.hass.callService("homeassistant", "toggle", { - entity_id: state.entity_id - }); - } - - static get styles() { - return css` - :host { - font-family: "Gloria Hallelujah", cursive; - } - wired-card { - background-color: white; - padding: 16px; - display: block; - font-size: 18px; - } - .state { - display: flex; - justify-content: space-between; - padding: 8px; - align-items: center; - } - .not-found { - background-color: yellow; - font-family: sans-serif; - font-size: 14px; - padding: 8px; - } - wired-toggle { - margin-left: 8px; - } - `; - } -} -customElements.define("wired-toggle-card", WiredToggleCard); -``` - -And for your configuration: - -```yaml -# Example Lovelace configuration -resources: - - url: /local/wired-cards.js - type: module -views: -- name: Example - cards: - - type: "custom:wired-toggle-card" - entities: - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_livingroom - - input_boolean.switch_tv -``` - -## Recommended Design Elements - -We are currently migrating from using Paper Elements to MWC (Material Web Component) Elements. - -If an element exists in the below repository for MWC. We recommended using it. - -- [MWC (Material Web Components)](https://material-components.github.io/material-components-web-components/demos/index.html) - -If an element does not exist in MWC, we default to using Paper Elements. - -- [Paper Elements](https://www.webcomponents.org/collection/PolymerElements/paper-elements) - -## Advanced Resources - -Community Maintained Boilerplate Card - Advanced Template (Typescript, Rollup, Linting, etc.) - -- [Boilerplate Card](https://github.com/custom-cards/boilerplate-card) - -Developer Documentation for [HACS](https://hacs.xyz/) (Home Assistant Community Store). - -- [HACS Plugin Docs](https://hacs.xyz/docs/publish/plugin) diff --git a/website/versioned_docs/version-0.103.0/api_lib_auth.md b/website/versioned_docs/version-0.103.0/api_lib_auth.md deleted file mode 100644 index 11663465..00000000 --- a/website/versioned_docs/version-0.103.0/api_lib_auth.md +++ /dev/null @@ -1,267 +0,0 @@ ---- -title: Python Library: Authentication -sidebar_label: Authentication -id: version-0.103.0-api_lib_auth -original_id: api_lib_auth ---- - -The Authentication part of your library is responsible for acquiring authentication and for making authenticated requests. It should not be aware of what is in the requests. - -Authentication comes in many forms, but it generally boils down to that each request is accompanied by an `authorization` header which contains an access token. The access token is generally a string of random numbers/letters. - -Your library should be able to acquire the authentication tokens, update them if necessary and use the authentication to make requests. It should not offer features to store the authentication data. - -Because authentication is going to be stored by the developer, it is important that you return the authentication to the developer in a format that can be JSON serializable. A `dict` with primitive types (`str`, `float`, `int`) is recommended. - -If your API can be served from multiple locations, your authentication class should allow the developer to pass in the location of the API. - -## Async example - -Python allows developers to write code that is either synchronous or asynchronous (via `asyncio`). Home Assistant is written in async, but is able to work with synchronous libraries too. We prefer async libraries. - -If you are writing a library in async, we recommend that you use `aiohttp`. It's a modern and mature HTTP library and is easy to use. - -```python -from aiohttp import ClientSession, ClientResponse - - -class Auth: - """Class to make authenticated requests.""" - - def __init__(self, websession: ClientSession, host: str, access_token: str): - """Initialize the auth.""" - self.websession = websession - self.host = host - self.access_token = access_token - - async def request(self, method: str, path: str, **kwargs) -> ClientResponse: - """Make a request.""" - headers = kwargs.get('headers') - - if headers is None: - headers = {} - else: - headers = dict(headers) - - headers["authorization"] = self.access_token - - return await self.websession.request( - method, - f"{self.host}/{path}", - **kwargs, - headers=headers, - ) -``` - -To use this class, you will need to create an aiohttp ClientSession and pass it together with the API info to the constructor. - -```python -import asyncio -import aiohttp - -from my_package import Auth - - -async def main(): - async with aiohttp.ClientSession() as session: - auth = Auth(session, "http://example.com/api", "secret_access_token") - - # This will fetch data from http://example.com/api/lights - resp = await auth.request('get', 'lights') - print("HTTP response status code", resp.status) - print("HTTP response JSON content", await resp.json()) - -asyncio.run(main()) -``` - -## Sync example - -```python -import requests - - -class Auth: - """Class to make authenticated requests.""" - - def __init__(self, host: str, access_token: str): - """Initialize the auth.""" - self.host = host - self.access_token = access_token - - async def request(self, method: str, path: str, **kwargs) -> requests.Response: - """Make a request.""" - headers = kwargs.get('headers') - - if headers is None: - headers = {} - else: - headers = dict(headers) - - headers["authorization"] = self.access_token - - return requests.request( - method, - f"{self.host}/{path}", - **kwargs, - headers=headers, - ) -``` - -To use this class, construct the class with the API info. - -```python -from my_package import Auth - - -auth = Auth("http://example.com/api", "secret_access_token") - -# This will fetch data from http://example.com/api/lights -resp = auth.request('get', 'lights') -print("HTTP response status code", resp.status_code) -print("HTTP response JSON content", resp.json()) -``` - -## OAuth2 - -OAuth2 is a [standardized version](https://tools.ietf.org/html/rfc6749) of an authentication schema leveraging refresh and access tokens. The access token expires within a short period of time after being issued. The refresh token can be used to acquire new access tokens. - -Refreshing access tokens relies on a client ID and secret, which might be held by an external service. We need to structure the authentication class to be able to allow the developer to implement their own token refresh logic. - -Home Assistant ships with the Home Assistant Cloud Account Linking service, a free cloud service to allow users to quickly connect accounts using OAuth2. Home Assistant has easy to use tools built-in to allow users to configure OAuth2-based integrations. For more info, [read here](config_entries_config_flow_handler.md#configuration-via-oauth2). These built-in tools work best if your library is implemented like the examples below. - -### Async example - -```python -from abc import ABC, abstractmethod - - -class AbstractAuth(ABC): - """Abstract class to make authenticated requests.""" - - def __init__(self, websession: ClientSession, host: str): - """Initialize the auth.""" - self.websession = websession - self.host = host - - @abstractmethod - async def async_get_access_token(self) -> str: - """Return a valid access token.""" - - async def request(self, method, url, **kwargs) -> ClientResponse: - """Make a request.""" - headers = kwargs.get('headers') - - if headers is None: - headers = {} - else: - headers = dict(headers) - - access_token = await self.async_get_access_token() - headers["authorization"] = f"Bearer {access_token}" - - return await self.websession.request( - method, - f"{self.host}/{url}", - **kwargs, - headers=headers, - ) -``` - -Now the developer that is using your library will have to implement the abstract method for getting the access token. Let's assume that the developer has their own token manager class. - -```python -from my_package import AbstractAuth - - -class Auth(AbstractAuth): - - def __init__(self, websession: ClientSession, host: str, token_manager): - """Initialize the auth.""" - super().__init__(websession, host) - self.token_manager = token_manager - - async def async_get_access_token(self) -> str: - """Return a valid access token.""" - if self.token_manager.is_token_valid(): - return self.token_manager.access_token - - await self.token_manager.fetch_access_token() - await self.token_manager.save_access_token() - - return self.token_manager.access_token -``` - -### Sync example - -If you are using `requests`, we recommend that you use the `requests_oauthlib` package. Below is an example that works with a local client ID and secret but also allows outsourcing token fetching to Home Assistant. - -```python -from typing import Optional, Union, Callable, Dict - -from requests import Response -from requests_oauthlib import OAuth2Session -from oauthlib.oauth2 import TokenExpiredError - - -class Auth: - def __init__( - self, - host: str, - token: Optional[Dict[str, str]] = None, - client_id: str = None, - client_secret: str = None, - token_updater: Optional[Callable[[str], None]] = None, - ): - self.host = host - self.client_id = client_id - self.client_secret = client_secret - self.token_updater = token_updater - - extra = {"client_id": self.client_id, "client_secret": self.client_secret} - - self._oauth = OAuth2Session( - auto_refresh_kwargs=extra, - client_id=client_id, - token=token, - token_updater=token_updater, - ) - - def refresh_tokens(self) -> Dict[str, Union[str, int]]: - """Refresh and return new tokens.""" - token = self._oauth.refresh_token(f"{self.host}/auth/token") - - if self.token_updater is not None: - self.token_updater(token) - - return token - - def request(self, method: str, path: str, **kwargs) -> Response: - """Make a request. - - We don't use the built-in token refresh mechanism of OAuth2 session because - we want to allow overriding the token refresh logic. - """ - url = f"{self.host}/{path}" - try: - return getattr(self._oauth, method)(url, **kwargs) - except TokenExpiredError: - self._oauth.token = self.refresh_tokens() - - return getattr(self._oauth, method)(url, **kwargs) -``` - -A developer will now be able to override the refresh token function to route it via their own external service. - -```python -from my_package import AbstractAuth - - -class Auth(AbstractAuth): - - def refresh_tokens(self) -> Dict[str, Union[str, int]]: - """Refresh and return new tokens.""" - self.token_manager.fetch_access_token() - self.token_manager.save_access_token() - - return self.token_manager.access_token -``` diff --git a/website/versioned_docs/version-0.103.0/app_integration_sending_data.md b/website/versioned_docs/version-0.103.0/app_integration_sending_data.md deleted file mode 100644 index f69a725a..00000000 --- a/website/versioned_docs/version-0.103.0/app_integration_sending_data.md +++ /dev/null @@ -1,230 +0,0 @@ ---- -title: Sending data home -id: version-0.103.0-app_integration_sending_data -original_id: app_integration_sending_data ---- - -Once you have registered your app with the mobile app component, you can start interacting with Home Assistant via the provided webhook information. - -The first step is to turn the returned webhook ID into a full URL: `/api/webhook/`. This will be the only url that we will need for all our interactions. The webhook endpoint will not require authenticated requests. - -If you were provided a Cloudhook URL during registration, you should use that by default and only fall back to a constructed URL as described above if that request fails. - -If you were provided a remote UI URL during registration, you should use that as the `instance_url` when constructing a URL and only fallback to the user provided URL if the remote UI URL fails. - -To summarize, here's how requests should be made: - -1. If you have a Cloudhook URL, use that until a request fails. When a request fails, go to step 2. -2. If you have a remote UI URL, use that to construct a webhook URL: `/api/webhook/`. When a request fails, go to step 3. -3. Construct a webhook URL using the instance URL provided during setup: `/api/webhook/`. - -## Short note on instance URLs - -Some users have configured Home Assistant to be available outside of their home network using a dynamic DNS service. There are some routers that don't support hairpinning / NAT loopback: a device sending data from inside the routers network, via the externally configured DNS service, to Home Asisstant, which also resides inside the local network. - -To work around this, the app should record which WiFi SSID is the users home network, and use a direct connection when connected to the home WiFi network. - -## Interaction basics - -### Request - -All interaction will be done by making HTTP POST requests to the webhook url. These requests do not need to contain authentication. - -The payload format depends on the type of interaction, but it all shares a common base: - -```json5 -{ - "type": "", - "data": {} -} -``` - -If you received a `secret` during registration, you **MUST** encrypt your message and put it in the payload like this: - -```json5 -{ - "type": "encrypted", - "encrypted": true, - "encrypted_data": "" -} -``` - -### Response - -As a general rule, expect to receive a 200 response for all your requests. There are a few cases in which you will receive another code: - -- You will receive a 400 status code if your JSON is invalid. However, you will not receive this error if the encrypted JSON is invalid. -- You will receive a 201 when creating a sensor -- If you receive a 404, the `mobile_app` component most likely isn't loaded. -- Receiving a 410 means the integration has been deleted. You should notify the user and most likely register again. - -## Implementing encryption - -`mobile_app` supports two way encrypted communication via [Sodium](https://libsodium.gitbook.io/doc/). - -> Sodium is a modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more. - -### Choosing a library -Libraries that wrap Sodium exist for most modern programming languages and platforms. Sodium itself is written in C. - -Here are the libraries we suggest using, although you should feel free to use whatever works well for you. - -- Swift/Objective-C: [swift-sodium](https://github.com/jedisct1/swift-sodium) (official library maintained by Sodium developers). - -For other languages, please see the list of [Bindings for other languages](https://download.libsodium.org/doc/bindings_for_other_languages). If more than one choice is available, we recommend using the choice most recently updated. - -### Configuration - -We use the [secret-key cryptography](https://download.libsodium.org/doc/secret-key_cryptography) features of Sodium to encrypt and decrypt payloads. All payloads are JSON encoded in Base64. For Base64 type, use `sodium_base64_VARIANT_ORIGINAL` (that is, "original", no padding, not URL safe). - -### Signaling encryption support - -During registration, you must set `supports_encryption` to `true` to enable encryption. The Home Assistant instance must be able to install `libsodium` to enable encryption. Confirm that you should make all future webhook requests encrypted by the presence of the key `secret` in the initial registration response. -You must store this secret forever. There is no way to recover it via the Home Assistant UI and you should **not** ask users to investigate hidden storage files to re-enter the encryption key. You should create a new registration if encryption ever fails and alert the user. - -## Update device location - -This message will inform Home Assistant of new location information. - -```json -{ - "type": "update_location", - "data": { - "gps": [12.34, 56.78], - "gps_accuracy": 120, - "battery": 45 - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `location_name` | string | Name of the zone the device is in. -| `gps` | latlong | Current location as latitude and longitude. -| `gps_accuracy` | int | GPS accurracy in meters. Must be greater than 0. -| `battery` | int | Percentage of battery the device has left. Must be greater than 0. -| `speed` | int | Speed of the device in meters per second. Must be greater than 0. -| `altitude` | int | Altitude of the device in meters. Must be greater than 0. -| `course` | int | The direction in which the device is traveling, measured in degrees and relative to due north. Must be greater than 0. -| `vertical_accuracy` | int | The accuracy of the altitude value, measured in meters. Must be greater than 0. - -## Call a service - -Call a service in Home Assistant. - -```json -{ - "type": "call_service", - "data": { - "domain": "light", - "service": "turn_on", - "service_data": { - "entity_id": "light.kitchen" - } - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `domain` | string | The domain of the service -| `service` | string | The service name -| `service_data` | dict | The data to send to the service - -## Fire an event - -Fire an event in Home Assistant. - -```json -{ - "type": "fire_event", - "data": { - "event_type": "my_custom_event", - "event_data": { - "something": 50 - } - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `event_type` | string | Type of the event to fire -| `event_data` | string | Date of the event to fire - -## Render templates - -Renders one or more templates and returns the result(s). - -```json -{ - "type": "render_template", - "data": { - "my_tpl": { - "template": "Hello {{ name }}, you are {{ states('person.paulus') }}.", - "variables": { - "name": "Paulus" - } - } - } -} -``` - -`data` must contain a map of `key`: `dictionary`. Results will be returned like `{"my_tpl": "Hello Paulus, you are home"}`. This allows for rendering multiple templates in a single call. - -| Key | Type | Description -| --- | ---- | ----------- -| `template` | string | The template to render -| `variables` | Dict | The extra template variables to include. - -## Update registration - -Update your app registration. Use this if the app version changed or any of the other values. - -```json -{ - "type": "update_registration", - "data": { - "app_data": { - "push_token": "abcd", - "push_url": "https://push.mycool.app/push" - }, - "app_version": "2.0.0", - "device_name": "Robbies iPhone", - "manufacturer": "Apple, Inc.", - "model": "iPhone XR", - "os_version": "23.02" - } -} -``` - -All keys are optional. - -| Key | Type | Description -| --- | --- | -- -| `app_data` | Dict | App data can be used if the app has a supporting component that extends mobile_app functionality or wishes to enable the notification platform. -| `app_version` | string | Version of the mobile app. -| `device_name` | string | Name of the device running the app. -| `manufacturer` | string | The manufacturer of the device running the app. -| `model` | string | The model of the device running the app. -| `os_version` | string | The OS version of the device running the app. - -## Get zones - -Get all enabled zones. - -```json -{ - "type": "get_zones" -} -``` - -## Get config - -Returns a version of `/api/config` with values useful for configuring your app. - -```json -{ - "type": "get_config" -} -``` diff --git a/website/versioned_docs/version-0.103.0/config_entries_config_flow_handler.md b/website/versioned_docs/version-0.103.0/config_entries_config_flow_handler.md deleted file mode 100644 index 1ae39897..00000000 --- a/website/versioned_docs/version-0.103.0/config_entries_config_flow_handler.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Integration Configuration -sidebar_label: Configuration -id: version-0.103.0-config_entries_config_flow_handler -original_id: config_entries_config_flow_handler ---- - -Integrations can be set up via the user interface by adding support for a config flow to create a config entry. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like Hass.io). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -## Updating the manifest - -You need to update your integrations manifest to inform Home Assistant that your integration has a config flow. This is done by adding `config_flow: true` to your manifest ([docs](creating_integration_manifest.md#config-flow)). - -## Defining your config flow - -Config entries uses the [data flow entry framework](data_entry_flow_index.md) to define their config flows. The config flow needs to be defined in the file `config_flow.py` in your integration folder, extend `homeassistant.config_entries.ConfigFlow` and pass a `domain` key as part of inheriting `ConfigFlow`. - -```python -from homeassistant import config_entries -from .const import DOMAIN - -class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): -``` - -Once you have updated your manifest and created the `config_flow.py`, you will need to run `python3 -m script.hassfest` (one time only) for Home Assistant to activate the config entry for your integration. - -## Defining steps - -Your config flow will need to define steps of your configuration flow. The docs for [Data Entry Flow](data_entry_flow_index.md) describe the different return values of a step. Here is an example on how to define the `user` step. - -```python -class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): - - async def async_step_user(self, info): - if info is not None: - # process info - - return self.async_show_form( - step_id='user', - data_schema=vol.Schema({ - vol.Required('password'): str - }) - ) -``` - -There are a few step names reserved for system use: - -| Step name | Description | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `user` | Invoked when a user initiates a flow via the user interface. | -| `zeroconf` | Invoked if your integration has been discovered via Zeroconf/mDNS as specified [using `zeroconf` in the manifest](creating_integration_manifest.md#zeroconf). | -| `homekit` | Invoked if your integration has been discovered via HomeKit as specified [using `homekit` in the manifest](creating_integration_manifest.md#homekit). | -| `ssdp` | Invoked if your integration has been discovered via SSDP/uPnP as specified [using `ssdp` in the manifest](creating_integration_manifest.md#ssdp). | -| `discovery` | _DEPRECATED_ Invoked if your integration has been discovered by the discovery integration. | - -## Discovery steps - -When an integration is discovered, their respective discovery step is invoked with the discovery information. The step will have to check the following things: - -- Make sure there are no other instances of this config flow in progress of setting up the discovered device. This can happen if there are multiple ways of discovering that a device is on the network. -- Make sure that the device is not already set up. -- Invoking a discovery step should never result in a finished flow and a config entry. Always confirm with the user. - -## Discoverable integrations that require no authentication - -If your integration is discoverable without requiring any authentication, you'll be able to use the Discoverable Flow that is built-in. This flow offers the following features: - -- Detect if devices/services can be discovered on the network before finishing the config flow. -- Support all manifest-based discovery protocols. -- Limit to only 1 config entry. It is up to the config entry to discover all available devices. - -To get started, run `python3 -m script.scaffold config_flow_discovery` and follow the instructions. This will create all the boilerplate necessary to configure your integration using discovery. - -## Configuration via OAuth2 - -Home Assistant has built-in support for integrations that offer account linking using [the OAuth2 authorization framework](https://tools.ietf.org/html/rfc6749). To be able to leverage this, you will need to structure your Python API library in a way that allows Home Assistant to be responsible for refreshing tokens. See our [API library guide](api_lib_index.md) on how to do this. - -The built-in OAuth2 support works out of the box with locally configured client ID / secret and with the Home Assistant Cloud Account Linking service. This service allows users to link their account with a centrally managed client ID/secret. If you want your integration to be part of this service, reach out to us at [hello@home-assistant.io](mailto:hello@home-assistant.io). - -To get started, run `python3 -m script.scaffold config_flow_oauth2` and follow the instructions. This will create all the boilerplate necessary to configure your integration using OAuth2. - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` - -When the translations are merged into Home Assistant, they will be automatically uploaded to [Lokalise](https://lokalise.co/) where the translation team will help to translate them in other languages. While developing locally, you will need to run `script/translations_develop` to see changes made to `strings.json` [More info on translating Home Assistant.](internationalization_translation.md) diff --git a/website/versioned_docs/version-0.103.0/creating_integration_manifest.md b/website/versioned_docs/version-0.103.0/creating_integration_manifest.md deleted file mode 100644 index 79849bfe..00000000 --- a/website/versioned_docs/version-0.103.0/creating_integration_manifest.md +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: Integration Manifest -sidebar_label: Manifest -id: version-0.103.0-creating_integration_manifest -original_id: creating_integration_manifest ---- - -Since 0.92.0, every integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, except for custom components. - -```json -{ - "domain": "hue", - "name": "Philips Hue", - "documentation": "https://www.home-assistant.io/components/hue", - "dependencies": ["mqtt"], - "codeowners": ["@balloob"], - "requirements": ["aiohue==1.9.1"] -} -``` - -Or a minimal example that you can copy into your project: - -```json -{ - "domain": "your_domain_name", - "name": "Your Integration", - "documentation": "https://www.example.com", - "dependencies": [], - "codeowners": [], - "requirements": [] -} -``` - -## Domain - -The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. - -## Name - -The name of the integration. - -## Documentation - -The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/` - -## Dependencies - -Dependencies are other Home Assistant integrations that you want Home Assistant to set up successfully prior to the integration being loaded. This can be necessary in case you want to offer functionality from that other integration, like using webhooks or an MQTT connection. - -## Code Owners - -GitHub usernames or team names of people that are responsible for this integration. You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included. - -## Config Flow - -Specify the `config_flow` key if your integration has a config flow to create a config entry. When specified, the file `config_flow.py` needs to exist in your integration. - -```json5 -{ - "config_flow": true -} -``` - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you are running in a virtual environment. This will make sure that all requirements are present at startup. If steps fail, like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is an array of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v3.2.0: `["pychromecast==3.2.0"]`. - -### Custom requirements during development & testing - -During the development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using `pychromecast` as an example: - -```bash -pip install pychromecast==3.2.0 --target ~/.homeassistant/deps -hass --skip-pip -``` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is specified in `requirements`. - -If you need to make changes to a requirement to support your component, it's also possible to install a development version of the requirement using `pip install -e`: - -```bash -git clone https://github.com/balloob/pychromecast.git -pip install -e ./pychromecast -hass --skip-pip -``` - -## Zeroconf - -If your integration supports discovery via [Zeroconf](https://en.wikipedia.org/wiki/Zero-configuration_networking), you can add the type to your manifest. If the user has the `zeroconf` integration loaded, it will load the `zeroconf` step of your integration's config flow when it is discovered. - -```json5 -{ - "zeroconf": ["_googlecast._tcp.local."] -} -``` - -## SSDP - -If your integration supports discovery via [SSDP](https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol), you can add the type to your manifest. If the user has the `ssdp` integration loaded, it will load the `ssdp` step of your integration's config flow when it is discovered. We support SSDP discovery by ST, and all data in UPnP device description. The manifest value is a list of matcher dictionaries, your integration is discovered if all items of any of the specified matchers are found in the SSDP/UPnP data. It's up to your config flow to filter out duplicates. - -The following example has one matcher consisting of three items, all of which must match for discovery to happen by this config. - -```json5 -{ - "ssdp": [ - { - "st": "roku:ecp", - "manufacturer": "Roku", - "deviceType": "urn:roku-com:device:player:1-0" - } - ] -} -``` - -## HomeKit - -If your integration supports discovery via HomeKit, you can add the supported model names to your manifest. If the user has the `zeroconf` integration loaded, it will load the `homekit` step of your integration's config flow when it is discovered. - -HomeKit discovery works by testing if the discovered modelname starts with any of the model names specified in the manifest.json. - -```json5 -{ - "homekit": { - "models": [ - "LIFX" - ] - } -} -``` - -Discovery via HomeKit does not mean that you have to talk the HomeKit protocol to communicate with your device. You can communicate with the device however you see fit. - -When a discovery info is routed to your integration because of this entry in your manifest, the discovery info is no longer routed to integrations that listen to the HomeKit zeroconf type. diff --git a/website/versioned_docs/version-0.103.0/development_testing.md b/website/versioned_docs/version-0.103.0/development_testing.md deleted file mode 100644 index 85f54e07..00000000 --- a/website/versioned_docs/version-0.103.0/development_testing.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Testing your code -id: version-0.103.0-development_testing -original_id: development_testing ---- - -As it states in the [Style guidelines section](development_guidelines.md) all code is checked to verify the following: - -- All the unit tests pass -- All code passes the checks from the linting tools - -Local testing is done using [Tox](https://tox.readthedocs.io), which has been installed as part of running `script/setup` in the [virtual environment](development_environment.md). To start the tests, activate the virtual environment and simply run the command: - -```bash -$ tox -``` - -It might be required that you install additional packages depending on your distribution/operating system: - -- Fedora: `sudo dnf -y install systemd-devel gcc-c++` -- Ubuntu: `sudo apt-get install libudev-dev` - -**Important:** Run `tox` before you create your pull request to avoid annoying fixes. - -Running `tox` will run unit tests against the locally available Python releases, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one `tox` target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py38` runs unit tests only on Python 3.8. - -`tox` uses virtual environments under the hood to create isolated testing environments. The `tox` virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell `tox` to recreate the virtual environments. - -macOS users may see an `Error creating virtualenv` when runnng `tox`. If this occurs, install the [tox-venv](https://pypi.org/project/tox-venv/) package using the command `pip install tox-venv` and try again. - -### Adding new dependencies to test environment - -If you are working on tests for an integeration and you need the dependencies available inside the `tox` environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments. - -### Running single tests using `tox` - -You can pass arguments via `tox` to `py.test` to be able to run single test suites or test files. Replace `py38` with the Python version that you use. - -```bash -# Stop after the first test fails -$ tox -e py38 -- tests/test_core.py -x -# Run test with specified name -$ tox -e py38 -- tests/test_core.py -k test_split_entity_id -# Fail a test after it runs for 2 seconds -$ tox -e py38 -- tests/test_core.py --timeout 2 -# Show the 10 slowest tests -$ tox -e py38 -- tests/test_core.py --duration=10 -``` - -### Testing outside of Tox - -Running `tox` will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without `tox`, you'll need to install the test dependencies into your Python environment: - -```bash -$ pip3 install -r requirements_test_all.txt -c homeassistant/package_constraints.txt -``` - -Now that you have all test dependencies installed, you can run tests on individual files: - -```bash -$ flake8 homeassistant/core.py -$ pylint homeassistant/core.py -$ pydocstyle homeassistant/core.py -$ py.test tests/test_core.py -``` - -You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script: - -```bash -$ script/lint -``` - -### Preventing linter errors - -Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them! - -```bash -$ pip3 install flake8 flake8-docstrings -$ flake8 --install-hook=git -``` - -The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8. - -### Notes on PyLint and PEP8 validation - -If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member. diff --git a/website/versioned_docs/version-0.103.0/external_api_rest.md b/website/versioned_docs/version-0.103.0/external_api_rest.md deleted file mode 100644 index 69d57739..00000000 --- a/website/versioned_docs/version-0.103.0/external_api_rest.md +++ /dev/null @@ -1,552 +0,0 @@ ---- -title: REST API -id: version-0.103.0-external_api_rest -original_id: external_api_rest ---- - -Home Assistant provides a RESTful API on the same port as the web frontend. (default port is port 8123). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -* http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -* http://IP_ADDRESS:8123/api/ is a RESTful API. - -The API accepts and returns only JSON encoded objects. - -All API calls have to be accompanied by the header `Authorization: Bearer ABCDEFGH`, where `ABCDEFGH` is replaced by your token. You can obtain a token ("Long-Lived Access Token") by logging into the frontend using a web browser, and going to [your profile](https://www.home-assistant.io/docs/authentication/#your-account-profile) `http://IP_ADDRESS:8123/profile`. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```bash -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. - -```python -from requests import get - -url = 'http://localhost:8123/ENDPOINT' -headers = { - 'Authorization': 'Bearer ABCDEFGH', - 'content-type': 'application/json', -} - -response = get(url, headers=headers) -print(response.text) -``` -Another option is to use the Restful Command component https://www.home-assistant.io/components/rest_command/ in a Home Assistant automation or script. - -```yaml -turn_light_on: - url: http://localhost:8123/api/states/light.study_light - method: POST - headers: - authorization: 'Bearer ABCDEFGH' - content-type: 'application/json' - payload: '{"state":"on"}' -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on one or more entities - comma separated. -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates a state. You can create any state that you want, it does not have to be backed by an entity in Home Assistant. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now() }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/config/core/check_config - -Trigger a check of `configuration.yaml`. No additional data needs to be passed in with this request. - -If the check is successful, the following will be returned: - -```javascript -{ - "errors": null, - "result": "valid" -} -``` - -If the check fails, the errors attribute in the object will list what caused the check to fail. For example: - -```javascript -{ - "errors": "Integration not found: frontend:", - "result": "invalid" -} -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance.
- -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` diff --git a/website/versioned_docs/version-0.103.0/hassio_addon_config.md b/website/versioned_docs/version-0.103.0/hassio_addon_config.md deleted file mode 100644 index af1f4693..00000000 --- a/website/versioned_docs/version-0.103.0/hassio_addon_config.md +++ /dev/null @@ -1,232 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.103.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - apparmor.txt - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -All our Images have also [bashio][bashio] installed. It contains a set of commonly used operations and can be used to be included in add-ons to reduce code duplication across add-ons and therefore making it easier to develop and maintain add-ons. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use bashio or `jq` inside your shell script to parse this data. - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -[bashio]: https://github.com/hassio-addons/bashio - -## Add-on Docker file - -All add-ons are based on latest Alpine Linux. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | yes | List of supported arch: `armhf`, `armv7`, `aarch64`, `amd64`, `i386`. -| machine | list | no | Default it support any machine type. You can select that this add-on run only on specific machines. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | string | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. If host-port is `null`, the mapping is disabled. -| ports_description | dict | no | Network ports description mapping. Format is `"container-port/type": "description of this port"`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| udev | bool | no | Default False. Set this True, if your container run a own udev process. -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| homeassistant | string | no | Pin a minimum required Home Assistant version for such Add-on. Value is a version string like `0.91.2`. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| kernel_modules | bool | no | Map host kernel modules and config into add-on (readonly). -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| auth_api | bool | no | Allow access to Home Assistent user backend. -| ingress | bool | no | Enable the ingress feature for the Add-on -| ingress_port | integer | no | Default `8099`. For Add-ons they run on host network, you can use `0` and read the port later on API. -| ingress_entry | string | no | Modify the URL entry point from `/`. -| panel_icon | string | no | Default: mdi:puzzle. MDI icon for the menu panel integration. -| panel_title | string | no | Default add-on name, but can Modify with this options. -| panel_admin | bool | no | Default True. Make menu entry only available with admin privileged. -| snapshot_exlude | list | no | List of file/path with glob support they are excluded from snapshots. - - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str / str(min,) / str(,max) / str(min,max) -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) -- list(val1|val2|...) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. - -We provide a set of [Base-Images][hassio-base] which should cover a lot of needs. If you don't want use the Alpine based version or need a specific Image tag, feel free to pin this requirements for you build with `build_from` option. - -[hassio-base]: https://github.com/home-assistant/hassio-base diff --git a/website/versioned_docs/version-0.103.0/internationalization_translation.md b/website/versioned_docs/version-0.103.0/internationalization_translation.md deleted file mode 100644 index ed67abe8..00000000 --- a/website/versioned_docs/version-0.103.0/internationalization_translation.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Translation -id: version-0.103.0-internationalization_translation -original_id: internationalization_translation ---- - -Translations for Home Assistant are managed through [Lokalise](https://lokalise.co/), an online translation management tool. Our translations are split between two projects, a backend project for platform-specific translations, and a frontend project for UI translations. Click the links below to join both projects! Even if your language is completely translated, extra proofreading is a big help! Please feel free to review the existing translations, and vote for alternatives that might be more appropriate. - -- [Join the frontend translation team](https://lokalise.co/signup/3420425759f6d6d241f598.13594006/all/) -- [Join the backend translation team](https://lokalise.co/signup/130246255a974bd3b5e8a1.51616605/all/) -- [Join the iOS translation team](https://lokalise.co/signup/834452985a05254348aee2.46389241/all/) -- [Join the Android translation team](https://lokalise.com/public/145814835dd655bc5ab0d0.36753359/) - -For more information about the translation workflow, please see the [Lokalise translation workflow documents](https://docs.lokalise.co/category/iOzEuQPS53-for-team-leads-and-translators). - -> The translation of the Home Assistant frontend is still a work in progress. More phrases will be available for translation soon. - -## Translation placeholders - -Some translation strings will contain special placeholders that will be replaced later. Placeholders shown in square brackets `[]` are [Lokalise key references](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing). These are primarily used to link translation strings that will be duplicated. Different languages may not have the same duplicates as English, and are welcome to link duplicate translations that are not linked in English. Placeholders shown in curly brackets `{}` are [translation arguments](https://formatjs.io/guides/message-syntax/) that will be replaced with a live value when Home Assistant is running. Any translation argument placeholders present in the original string must be included in the translated string. These may include special syntax for defining plurals or other replacement rules. The linked format.js guide explains the syntax for adding plural definitions and other rules. - -## Rules -1. Only native speakers should submit translations. -2. Stick to [Material Design guidelines](https://material.io/guidelines/style/writing.html). -3. Don't translate or change proper nouns like `Home Assistant`, `Hass.io` or `Hue`. -4. For a region specific translation, keys that will be the same as the base translation should be filled with `[VOID]`. These will be replaced during our translation build process. -5. Translations under the `state_badge` keys will be used for the notification badge display. These translations should be short enough to fit in the badge label without overflowing. This can be tested in the Home Assistant UI either by editing the label text with your browsers development tools, or by using the States states dev tool icon developer tool in the Home Assistant UI. In the UI, enter a new entity ID (`device_tracker.test`), and enter the text you want to test in state. -6. If text will be duplicated across different translation keys, make use of the Lokalise key reference feature where possible. The base translation provides examples of this underneath the `states` translations. Please see the [Lokalise key referencing](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing) documentation for more details. - -## Adding a new language -If your language is not listed you can request it at [GitHub](https://github.com/home-assistant/home-assistant-polymer/issues/new). Please provide both the English name and the native name for your language. For example: -``` -English Name: German -Native Name: Deutsch -``` - -> Region specific translations (`en-US`, `fr-CA`) will only be included if translations for that region need to differ from the base language translation. - -### Maintainer steps to add a new language -1. Language tags have to follow [BCP 47](https://tools.ietf.org/html/bcp47). A list of most language tags can be found here: [IANA sutbtag registry](http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry). Examples: `fr`, `fr-CA`, `zh-Hans`. Only include the country code if country specific overrides are being included, and the base language is already translated. -2. Add the language tag and native name in `src/translations/translationMetadata.json`. Examples: "Français", "Français (CA)" -3. Add the new language in Lokalize. -Note: Sometimes you have to change the tag in Lokalise (Language -> Language settings -> custom ISO code). diff --git a/website/versioned_docs/version-0.103.0/maintenance.md b/website/versioned_docs/version-0.103.0/maintenance.md deleted file mode 100644 index fa697391..00000000 --- a/website/versioned_docs/version-0.103.0/maintenance.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Maintenance -id: version-0.103.0-maintenance -original_id: maintenance ---- - -This page documents a couple of points for maintaining the Home Assistant code. Most of the tasks don't need to be performed on a regular base thus the steps, used tools, or details are preserved here. - -## Source code - -### Line separator - -People are using various operating systems to develop components and platforms for Home Assistant. This could lead to different line endings on file. We prefer `LN`. Especially Microsoft Windows tools tend to use `CRLF`. - -```bash -$ find homeassistant -name "*.py" -exec file {} \; | grep BOM -$ find homeassistant -name "*.py" -exec file {} \; | grep CRLF -``` - -To fix the line separator, use `dos2unix` or `sed`. - -```bash -$ dos2unix homeassistant/components/notify/kodi.py -``` - -### File permissions - -Most files don't need to the be executable. `0644` is fine. - -### Dependencies - -A lot of components and platforms depends on third-party Python modules. The dependencies which are stored in the `requirements_all.txt` files can be tracked with [`pur`](https://pypi.org/project/pur/) or [`pip-upgrader`](https://github.com/simion/pip-upgrader). - -If you update the requirements of a component/platform by updating `manifest.json`, run the provided script to update the `requirements_*.txt` file(s). - -```bash -$ script/gen_requirements_all.py -``` - -Start a test run of Home Assistant. If that was successful, include all files in a Pull Request. Add a short summary of the changes, a sample configuration entry, details about the tests you performed to ensure the update works, and other useful information to the description. - - -## Documentation - -- Merge `current` into `next` on a regular base. -- Optimize the images. - diff --git a/website/versioned_docs/version-0.104.0/api_lib_auth.md b/website/versioned_docs/version-0.104.0/api_lib_auth.md deleted file mode 100644 index d598c38e..00000000 --- a/website/versioned_docs/version-0.104.0/api_lib_auth.md +++ /dev/null @@ -1,257 +0,0 @@ ---- -title: Python Library: Authentication -sidebar_label: Authentication -id: version-0.104.0-api_lib_auth -original_id: api_lib_auth ---- - -The Authentication part of your library is responsible for acquiring authentication and for making authenticated requests. It should not be aware of what is in the requests. - -Authentication comes in many forms, but it generally boils down to that each request is accompanied by an `authorization` header which contains an access token. The access token is generally a string of random numbers/letters. - -Your library should be able to acquire the authentication tokens, update them if necessary and use the authentication to make requests. It should not offer features to store the authentication data. - -Because authentication is going to be stored by the developer, it is important that you return the authentication to the developer in a format that can be JSON serializable. A `dict` with primitive types (`str`, `float`, `int`) is recommended. - -If your API can be served from multiple locations, your authentication class should allow the developer to pass in the location of the API. - -## Async example - -Python allows developers to write code that is either synchronous or asynchronous (via `asyncio`). Home Assistant is written in async, but is able to work with synchronous libraries too. We prefer async libraries. - -If you are writing a library in async, we recommend that you use `aiohttp`. It's a modern and mature HTTP library and is easy to use. - -```python -from aiohttp import ClientSession, ClientResponse - - -class Auth: - """Class to make authenticated requests.""" - - def __init__(self, websession: ClientSession, host: str, access_token: str): - """Initialize the auth.""" - self.websession = websession - self.host = host - self.access_token = access_token - - async def request(self, method: str, path: str, **kwargs) -> ClientResponse: - """Make a request.""" - headers = kwargs.get("headers") - - if headers is None: - headers = {} - else: - headers = dict(headers) - - headers["authorization"] = self.access_token - - return await self.websession.request( - method, f"{self.host}/{path}", **kwargs, headers=headers, - ) -``` - -To use this class, you will need to create an aiohttp ClientSession and pass it together with the API info to the constructor. - -```python -import asyncio -import aiohttp - -from my_package import Auth - - -async def main(): - async with aiohttp.ClientSession() as session: - auth = Auth(session, "http://example.com/api", "secret_access_token") - - # This will fetch data from http://example.com/api/lights - resp = await auth.request("get", "lights") - print("HTTP response status code", resp.status) - print("HTTP response JSON content", await resp.json()) - - -asyncio.run(main()) -``` - -## Sync example - -```python -import requests - - -class Auth: - """Class to make authenticated requests.""" - - def __init__(self, host: str, access_token: str): - """Initialize the auth.""" - self.host = host - self.access_token = access_token - - async def request(self, method: str, path: str, **kwargs) -> requests.Response: - """Make a request.""" - headers = kwargs.get("headers") - - if headers is None: - headers = {} - else: - headers = dict(headers) - - headers["authorization"] = self.access_token - - return requests.request( - method, f"{self.host}/{path}", **kwargs, headers=headers, - ) -``` - -To use this class, construct the class with the API info. - -```python -from my_package import Auth - - -auth = Auth("http://example.com/api", "secret_access_token") - -# This will fetch data from http://example.com/api/lights -resp = auth.request("get", "lights") -print("HTTP response status code", resp.status_code) -print("HTTP response JSON content", resp.json()) -``` - -## OAuth2 - -OAuth2 is a [standardized version](https://tools.ietf.org/html/rfc6749) of an authentication schema leveraging refresh and access tokens. The access token expires within a short period of time after being issued. The refresh token can be used to acquire new access tokens. - -Refreshing access tokens relies on a client ID and secret, which might be held by an external service. We need to structure the authentication class to be able to allow the developer to implement their own token refresh logic. - -Home Assistant ships with the Home Assistant Cloud Account Linking service, a free cloud service to allow users to quickly connect accounts using OAuth2. Home Assistant has easy to use tools built-in to allow users to configure OAuth2-based integrations. For more info, [read here](config_entries_config_flow_handler.md#configuration-via-oauth2). These built-in tools work best if your library is implemented like the examples below. - -### Async example - -```python -from abc import ABC, abstractmethod - - -class AbstractAuth(ABC): - """Abstract class to make authenticated requests.""" - - def __init__(self, websession: ClientSession, host: str): - """Initialize the auth.""" - self.websession = websession - self.host = host - - @abstractmethod - async def async_get_access_token(self) -> str: - """Return a valid access token.""" - - async def request(self, method, url, **kwargs) -> ClientResponse: - """Make a request.""" - headers = kwargs.get("headers") - - if headers is None: - headers = {} - else: - headers = dict(headers) - - access_token = await self.async_get_access_token() - headers["authorization"] = f"Bearer {access_token}" - - return await self.websession.request( - method, f"{self.host}/{url}", **kwargs, headers=headers, - ) -``` - -Now the developer that is using your library will have to implement the abstract method for getting the access token. Let's assume that the developer has their own token manager class. - -```python -from my_package import AbstractAuth - - -class Auth(AbstractAuth): - def __init__(self, websession: ClientSession, host: str, token_manager): - """Initialize the auth.""" - super().__init__(websession, host) - self.token_manager = token_manager - - async def async_get_access_token(self) -> str: - """Return a valid access token.""" - if self.token_manager.is_token_valid(): - return self.token_manager.access_token - - await self.token_manager.fetch_access_token() - await self.token_manager.save_access_token() - - return self.token_manager.access_token -``` - -### Sync example - -If you are using `requests`, we recommend that you use the `requests_oauthlib` package. Below is an example that works with a local client ID and secret but also allows outsourcing token fetching to Home Assistant. - -```python -from typing import Optional, Union, Callable, Dict - -from requests import Response -from requests_oauthlib import OAuth2Session -from oauthlib.oauth2 import TokenExpiredError - - -class Auth: - def __init__( - self, - host: str, - token: Optional[Dict[str, str]] = None, - client_id: str = None, - client_secret: str = None, - token_updater: Optional[Callable[[str], None]] = None, - ): - self.host = host - self.client_id = client_id - self.client_secret = client_secret - self.token_updater = token_updater - - extra = {"client_id": self.client_id, "client_secret": self.client_secret} - - self._oauth = OAuth2Session( - auto_refresh_kwargs=extra, - client_id=client_id, - token=token, - token_updater=token_updater, - ) - - def refresh_tokens(self) -> Dict[str, Union[str, int]]: - """Refresh and return new tokens.""" - token = self._oauth.refresh_token(f"{self.host}/auth/token") - - if self.token_updater is not None: - self.token_updater(token) - - return token - - def request(self, method: str, path: str, **kwargs) -> Response: - """Make a request. - - We don't use the built-in token refresh mechanism of OAuth2 session because - we want to allow overriding the token refresh logic. - """ - url = f"{self.host}/{path}" - try: - return getattr(self._oauth, method)(url, **kwargs) - except TokenExpiredError: - self._oauth.token = self.refresh_tokens() - - return getattr(self._oauth, method)(url, **kwargs) -``` - -A developer will now be able to override the refresh token function to route it via their own external service. - -```python -from my_package import AbstractAuth - - -class Auth(AbstractAuth): - def refresh_tokens(self) -> Dict[str, Union[str, int]]: - """Refresh and return new tokens.""" - self.token_manager.fetch_access_token() - self.token_manager.save_access_token() - - return self.token_manager.access_token -``` diff --git a/website/versioned_docs/version-0.104.0/api_lib_data_models.md b/website/versioned_docs/version-0.104.0/api_lib_data_models.md deleted file mode 100644 index b9ce98e3..00000000 --- a/website/versioned_docs/version-0.104.0/api_lib_data_models.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: Python Library: Modelling Data -sidebar_label: Modelling Data -id: version-0.104.0-api_lib_data_models -original_id: api_lib_data_models ---- - -Now that we have authentication going, we can start making authenticated requests and fetch data! - -When modelling the data, it is important that we expose the data from the API in the same structure as that the API offers it. Some API designs might not make a lot of sense or contain typos. It is important that we still represent them in our objects. This makes it easy for developers using your library to follow the API documentation and know how it will work in your library. - -API libraries should try to do as little as possible. So it is okay to represent data structures as classes, but you should not transform data from one value into another. For example, you should not implement conversion between Celsius and Fahrenheit temperatures. This involves making decisions on precisions of results and should therefore be left to the developer using the library. - -For this example we're going to model an async library for a Rest API named ExampleHub that has two endpoints: - -- get `/light/`: query the information of a single light. - - ```json - { - "id": 1234, - "name": "Example Light", - "is_on": true - } - ``` - -- post `/light/`: control the light. Example JSON to send: `{ "is_on": false }`. Responds with the new state of the light. - -- get `/lights`: return a list of all lights - ```json - [ - { - "id": 1234, - "name": "Example Light", - "is_on": true - }, - { - "id": 5678, - "name": "Example Light 2", - "is_on": false - } - ] - ``` - -As this API represents lights, we're first going to create a class to represent a light. - -```python -from .auth import Auth - - -class Light: - """Class that represents a Light object in the ExampleHub API.""" - - def __init__(self, raw_data: dict, auth: Auth): - """Initialize a light object.""" - self.raw_data = raw_data - self.auth = auth - - # Note: each property name maps the name in the returned data - - @property - def id(self) -> int: - """Return the ID of the light.""" - return self.raw_data["id"] - - @property - def name(self) -> str: - """Return the name of the light.""" - return self.raw_data["name"] - - @property - def is_on(self) -> bool: - """Return if the light is on.""" - return self.raw_data["id"] - - async def async_control(self, is_on: bool): - """Control the light.""" - resp = await self.auth.request( - "post", f"light/{self.id}", json={"is_on": is_on} - ) - resp.raise_for_status() - self.raw_data = await resp.json() - - async def async_update(self): - """Update the light data.""" - resp = await self.auth.request("get", f"light/{self.id}") - resp.raise_for_status() - self.raw_data = await resp.json() -``` - -Now that we have a light class, we can model the root of the API, which provides the entry points into the data. - -```python -from typing import List - -from .auth import Auth -from .light import Light - - -class ExampleHubAPI: - """Class to communicate with the ExampleHub API.""" - - def __init__(self, auth: Auth): - """Initialize the API and store the auth so we can make requests.""" - self.auth = auth - - async def async_get_lights(self) -> List[Light]: - """Return the lights.""" - resp = await self.auth.request("get", "lights") - resp.raise_for_status() - return [Light(light_data, self.auth) for light_data in await resp.json()] - - async def async_get_light(self, light_id) -> Light: - """Return the lights.""" - resp = await self.auth.request("get", f"light/{light_id}") - resp.raise_for_status() - return Light(await resp.json(), self.auth) -``` - -With these two files in place, we can now control our lights like this: - -```python -import asyncio -import aiohttp - -from my_package import Auth, ExampleHubAPI - - -async def main(): - async with aiohttp.ClientSession() as session: - auth = Auth(session, "http://example.com/api", "secret_access_token") - api = ExampleHubAPI(auth) - - lights = await api.async_get_lights() - - # Print light states - for light in lights: - print(f"The light {light.name} is {light.is_on}") - - # Control a light. - light = lights[0] - await light.async_control(not light.is_on) - - -asyncio.run(main()) -``` diff --git a/website/versioned_docs/version-0.104.0/api_lib_index.md b/website/versioned_docs/version-0.104.0/api_lib_index.md deleted file mode 100644 index 860a25a0..00000000 --- a/website/versioned_docs/version-0.104.0/api_lib_index.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Building a Python library for an API -sidebar_label: Introduction -id: version-0.104.0-api_lib_index -original_id: api_lib_index ---- - -One of the foundational rules of Home Assistant is that we do not include any protocol specific code. Instead, this code should be put into a standalone Python library and published to PyPI. This guide will describe how to get started with this! - -For this guide we're going to assume that we're building a library for a Rest API that is accessible over HTTP and returning data structured as JSON objects. This is the most common type of API that we see. These APIs can either be accessible on the device itself, or in the cloud. - -This guide is not a perfect fit for every API. You might have to tweak the examples. - -> If you are a manufacturer designing a new API for your product, [please read about the best type of API to add to your products here](https://www.home-assistant.io/blog/2016/02/12/classifying-the-internet-of-things/#local-device-pushing-new-state). - -HTTP API requests consist of four different parts: - -- The URL. This is the path that we fetch data from. With a Rest API the URL will uniquely identify the resource. Examples of urls are `http://example.com/api/lights` and `http://example.com/api/light/1234`. -- The HTTP method. This defines what we want from the API. The most common ones are: - - `GET` for when we want to get information like the state of a light - - `POST` for if we want something to be done (ie turn on a light) -- The body. This is the data that we sent to the server to identify what needs to be done. This is how we send the command in the case of a `POST` request. -- The headers. This contains metadata to describe your request. This will used to attach the authorization to the request. - -## Structuring the library - -Our library will consist of two different parts: - -- **Authentication:** Responsible for making authenticated HTTP requests to the API endpoint and returning the results. This is the only piece of code that will actually interact with the API. -- **Data models:** Represent the data and offer commands to interact with the data. - -## Trying your library inside Home Assistant - -You will need to run an editable version of your library if you want to try your library in Home Assistant before it is publised to PyPI. - -Do so by going to your Home Assistant development environment, activating the virtual environment and typing: - -```shell -pip3 install -e ../my_lib_folder -``` - -Now run Home Assistant without installing dependencies from PyPI to avoid overriding your package. - -```shell -hass --skip-pip -``` diff --git a/website/versioned_docs/version-0.104.0/app_integration_setup.md b/website/versioned_docs/version-0.104.0/app_integration_setup.md deleted file mode 100644 index 294c9600..00000000 --- a/website/versioned_docs/version-0.104.0/app_integration_setup.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: Connecting to an instance -id: version-0.104.0-app_integration_setup -original_id: app_integration_setup ---- - -When a user first opens the app, they will need to connect to their local instance to authenticate and register the device. - -## Authenticating the user - -The local instance can be discovered if Home Assistant has the [zeroconf component] configured by searching for `_home-assistant._tcp.local.`. If not configured, the user will need to be asked for the local address of their instance. - -When the address of the instance is known, the app will ask the user to authenticate via [OAuth2 with Home Assistant]. Home Assistant uses IndieAuth, which means that to be able to redirect to a url that triggers your app, you need to take some extra steps. Make sure to read the last paragraph of the "Clients" section thoroughly. - -[zeroconf component]: https://www.home-assistant.io/components/zeroconf -[OAuth2 with Home Assistant]: auth_api.md - -## Registering the device - -_This requires Home Assistant 0.90 or later._ - -Home Assistant has a `mobile_app` component that allows applications to register themselves and interact with the instance. This is a generic component to handle most common mobile application tasks. This component is extendable with custom interactions if your app needs more types of interactions than are offered by this component. - -Once you have tokens to authenticate as a user, it's time to register the app with the mobile app component in Home Assistant. - -### Getting Ready - -First, you must ensure that the `mobile_app` component is loaded. There are two ways to do this: - -- You can publish a Zeroconf/Bonjour record `_hass-mobile-app._tcp.local.` to trigger the automatic load of the `mobile_app` component. You should wait at least 60 seconds after publishing the record before continuing. -- You can ask the user to add `mobile_app` to their configuration.yaml and restart Home Assistant. If the user already has `default_config` in their configuration, then `mobile_app` will have been already loaded. - -You can confirm the `mobile_app` component has been loaded by checking the `components` array of the [`/api/config` REST API call](external_api_rest.md#get-api-config). If you continue to device registration and receive a 404 status code, then it most likely hasn't been loaded yet. - -### Registering the device - -To register the device, make an authenticated POST request to `/api/mobile_app/registrations`. [More info on making authenticated requests.](auth_api.md#making-authenticated-requests) - -Example payload to send to the registration endpoint: - -```json -{ - "device_id": "ABCDEFGH", - "app_id": "awesome_home", - "app_name": "Awesome Home", - "app_version": "1.2.0", - "device_name": "Robbies iPhone", - "manufacturer": "Apple, Inc.", - "model": "iPhone X", - "os_name": "iOS", - "os_version": "iOS 10.12", - "supports_encryption": true, - "app_data": { - "push_notification_key": "abcdef" - } -} -``` - -| Key | Required | Type | Description | -| --------------------- | -------- | ------ | --------------------------------------------------------------------------------------------------- | -| `device_id` | V | string | A unique identifier for this device. New in Home Assistant 0.104 | -| `app_id` | V | string | A unique identifier for this app. | -| `app_name` | V | string | Name of the mobile app. | -| `app_version` | V | string | Version of the mobile app. | -| `device_name` | V | string | Name of the device running the app. | -| `manufacturer` | V | string | The manufacturer of the device running the app. | -| `model` | V | string | The model of the device running the app. | -| `os_name` | V | string | The name of the OS running the app. | -| `os_version` | V | string | The OS version of the device running the app. | -| `supports_encryption` | V | bool | If the app supports encryption. See also the [encryption section](#encryption). | -| `app_data` | | Dict | App data can be used if the app has a supporting component that extends `mobile_app` functionality. | - -When you get a 200 response, the mobile app is registered with Home Assistant. The response is a JSON document and will contain the URLs on how to interact with the Home Assistant instance. You should permanently store this information. - -```json -{ - "cloudhook_url": "https://hooks.nabu.casa/randomlongstring123", - "remote_ui_url": "https://randomlongstring123.ui.nabu.casa", - "secret": "qwerty", - "webhook_id": "abcdefgh" -} -``` - -| Key | Type | Description | -| --------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `cloudhook_url` | string | The cloudhook URL provided by Home Assistant Cloud. Only will be provided if user is actively subscribed to Nabu Casa. | -| `remote_ui_url` | string | The remote UI URL provided by Home Assistant Cloud. Only will be provided if user is actively subscribed to Nabu Casa. | -| `secret` | string | The secret to use for encrypted communication. Will only be included if encryption is supported by both the app and the Home Assistant instance. [More info](app_integration_sending_data.md#implementing-encryption). | -| `webhook_id` | string | The webhook ID that can be used to send data back. | diff --git a/website/versioned_docs/version-0.104.0/asyncio_categorizing_functions.md b/website/versioned_docs/version-0.104.0/asyncio_categorizing_functions.md deleted file mode 100644 index 56539b89..00000000 --- a/website/versioned_docs/version-0.104.0/asyncio_categorizing_functions.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: Categorizing Functions -id: version-0.104.0-asyncio_categorizing_functions -original_id: asyncio_categorizing_functions ---- - -A piece of work within Home Assistant is represented by a function that will be invoked. It will either run inside our event loop or inside our thread pool, depending on if it is async safe. - -Home Assistant uses the convention that all functions that must be run from within the event loop are prefixed with `async_`. - -## The coroutine function - -Coroutines are special functions based on Python’s generators syntax which allows them to suspend execution while waiting on a result. - -Invoking a coroutine function will return a Generator object back, but will not actually begin execution. This object will execute the task when it is either awaited (from within another coroutine) or it is scheduled on the event loop. - -To declare a function a coroutine, add `async` before the `def` of the function definition. - -```python -async def async_look_my_coroutine(target): - result = await entity.async_turn_on() - if result: - print(f"hello {target}") - - -hass.loop.create_task(async_look_my_coroutine("world")) -``` - -In this example, we schedule the coroutine by calling `hass.loop.create_task`. This will add the coroutine to the queue of tasks to be run. When the event loop is running `async_look_my_coroutine` it will suspend the task when `await entity.async_turn_on()` is called. At that point a new task will be scheduled to execute `entity.async_turn_on()`. When that job has been executed, `async_look_my_coroutine` will resume. - -## The callback function - -This is a normal function that is considered safe to be run from within the event loop. A callback is unable to suspend itself and thus cannot do any I/O or call a coroutine. A callback is capable of scheduling a new task but it will not be able to wait for the results. - -To declare a function as a callback, import the callback annotation from the core package and annotate your function. - -A common use case for a callback in Home Assistant is as a listener for an event or a service call. It can process the incoming information and then schedule the right calls to be made. Example from the automation component. - -```python -from homeassistant.core import callback - - -@callback -def async_trigger_service_handler(service_call): - """Handle automation trigger service calls.""" - vars = service_call.data.get(ATTR_VARIABLES) - for entity in component.async_extract_from_service(service_call): - hass.loop.create_task(entity.async_trigger(vars, True)) -``` - -In this example, `entity.async_trigger` is a coroutine function. Invoking the coroutine function will return a coroutine task. The passed in parameters will be used when the task gets executed. - -To execute the task we have to schedule it for execution on the event loop. This is done by calling `hass.loop.create_task`. - -### Why even have callbacks? - -You might wonder, if a coroutine can do everything a callback can do, why even have a callback. The reason is performance and better state consistency of the core API objects. - -When coroutine A waits for coroutine B, it will suspend itself and schedule a new task to run B. This means that the event loop is now running A, B and then A again. If B is a callback, A will never have to suspend itself and thus the event loop is just running A. The consistency implication is that other events queued to run on the event loop continue to wait until callbacks complete, but will be interleaved when yielding to another coroutine. - -## Event loop and thread safe - -These are functions that are safe to run both in a thread and inside the event loop. These functions are usually performing a computation or transform data in memory. Anything that does I/O does not fall under this category. Many standard library functions fall in this category. For example generating the sum of a set of numbers using sum or merging two dictionaries. - -There is no special annotation to mark functions as part of this category and care should be taken when using these functions from inside the event loop. When in doubt, look at their implementation. - -## Other functions - -These are all the functions that did not fit in the previous categories. These functions are either thread-safe or not considered safe to be run within the event loop. These are functions that use sleep, or perform I/O. - -There is no special annotation necessary to be considered part of this category. diff --git a/website/versioned_docs/version-0.104.0/asyncio_working_with_async.md b/website/versioned_docs/version-0.104.0/asyncio_working_with_async.md deleted file mode 100644 index f847551c..00000000 --- a/website/versioned_docs/version-0.104.0/asyncio_working_with_async.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Working with Async -id: version-0.104.0-asyncio_working_with_async -original_id: asyncio_working_with_async ---- - -Although we have a backwards compatible API, using the async core directly will be a lot faster. Most core components have already been rewritten to leverage the async core. This includes the EntityComponent helper (foundation of light, switch, etc), scripts, groups and automation. - -## Interacting with the core - -[All methods in the Home Assistant core][dev-docs] are implemented in two flavors: an async version and a version to be called from other threads. The versions for other are merely wrappers that call the async version in a threadsafe manner. - -So if you are making calls to the core (the hass object) from within a callback or coroutine, use the methods that start with async_. If you need to call an async_ function that is a coroutine, your task must also be a coroutine. - -## Implementing an async component - -To make a component async, implement an async_setup. - -```python -def setup(hass, config): - """Set up component.""" - # Code for setting up your component outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup(hass, config): - """Set up component.""" - # Code for setting up your component inside of the event loop. -``` - -## Implementing an async platform - -For platforms we support async setup. Instead of setup_platform you need to have a coroutine async_setup_platform. - -```python -def setup_platform(hass, config, add_entities, discovery_info=None): - """Set up platform.""" - # Code for setting up your platform outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup_platform(hass, config, async_add_entities, discovery_info=None): - """Set up platform.""" - # Code for setting up your platform inside of the event loop. -``` - -The only difference with the original parameters is that the `add_entities` function has been replaced by the async friendly callback `async_add_entities`. - -## Implementing an async entity - -You can make your entity async friendly by converting your update method to be async. This requires the dependency of your entities to also be async friendly! - -```python -class MyEntity(Entity): - def update(self): - """Retrieve latest state.""" - self._state = fetch_state() -``` - -Will turn into: - -```python -class MyEntity(Entity): - async def async_update(self): - """Retrieve latest state.""" - self._state = await async_fetch_state() -``` - -Make sure that all properties defined on your entity do not result in I/O being done. All data has to be fetched inside the update method and cached on the entity. This is because these properties are read from within the event loop and thus doing I/O will result in the core of Home Assistant waiting until your I/O is done. - -## Calling async functions from threads - -Sometimes it will happen that you’re in a thread and you want to call a function that is only available as async. Home Assistant includes a few async helper utilities to help with this. - -In the following example, `say_hello` will schedule `async_say_hello` and block till the function has run and get the result back. - -```python -import asyncio - - -def say_hello(hass, target): - return asyncio.run_coroutine_threadsafe( - async_say_hello(hass, target), hass.loop - ).result() - - -async def async_say_hello(hass, target): - return f"Hello {target}!" -``` - -## Calling sync functions from async - -If you are running inside an async context, it might sometimes be necessary to call a sync function. Do this like this: - -```python -# hub.update() is a sync function. -result = await hass.async_add_executor_job(hub.update) -``` - -## Starting independent task from async - -If you want to spawn a task that will not block the current async context, you can choose to create it as a task on the event loop. It will then be executed in parallel. - -```python -hass.async_create_task(async_say_hello(hass, target)) -``` - - -[dev-docs]: https://dev-docs.home-assistant.io/en/master/api/core.html -[dev-docs-async]: https://dev-docs.home-assistant.io/en/dev/api/util.html#module-homeassistant.util.async diff --git a/website/versioned_docs/version-0.104.0/auth_api.md b/website/versioned_docs/version-0.104.0/auth_api.md deleted file mode 100644 index 404c2108..00000000 --- a/website/versioned_docs/version-0.104.0/auth_api.md +++ /dev/null @@ -1,257 +0,0 @@ ---- -title: Authentication API -sidebar_label: API -id: version-0.104.0-auth_api -original_id: auth_api ---- - -This page will describe the steps required for your application to authorize against and integrate with Home Assistant instances. [See a demo](https://hass-auth-demo.glitch.me) powered by our helper lib [home-assistant-js-websocket](https://github.com/home-assistant/home-assistant-js-websocket). - -Each user has their own instance of Home Assistant which gives each user control over their own data. However, we also wanted to make it easy for third party developers to create applications that allow users to integrate with Home Assistant. To achieve this, we have adopted the [OAuth 2 specification][oauth2-spec] combined with the [OAuth 2 IndieAuth extension][indieauth-spec] for generating clients. - -## Clients - -Before you can ask the user to authorize their instance with your application, you will need a client. In traditional OAuth2, the server needs to generate a client before a user can authorize. However, as each server belongs to a user, we've adopted a slightly different approach from [IndieAuth][indieauth-clients]. - -The client ID you need to use is the website of your application. The redirect url has to be of the same host and port as the client ID. For example: - - - client id: `https://www.my-application.io` - - redirect uri: `https://www.my-application.io/hass/auth_callback` - -If you require a different redirect url (ie, if building a native app), you can add an HTML tag to the content of the website of your application (the client ID) with an approved redirect url. For example, add this to your site to whitelist redirect uri `hass://auth`: - -```html - -``` - -Home Assistant will scan the first 10kB of a website for link tags. - -## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) - -> All example URLs here are shown with extra spaces and new lines for display purposes only. - -The authorize url should contain `client_id` and `redirect_uri` as query parameters. - -``` -http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2F%3Fauth_callback%3D1 -``` - -Optionally you can also include a `state` parameter, this will be added to the redirect uri. The state is perfect to store the instance url that you are authenticating with. Example: - -``` -http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2Fauth_callback& - state=http%3A%2F%2Fhassio.local%3A8123 -``` - -The user will navigate to this link and be presented with instructions to log in and authorize your application. Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code and state as part of the query parameters. Example: - -``` -https://hass-auth-demo.glitch.me/auth_callback - code=12345& - state=http%3A%2F%2Fhassio.local%3A8123 -``` - -This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section). - -## Token - -The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. In thee case of refresh token, the token endpoint is also capable of revoking a token. - -All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`. - -### Authorization code - -> All requests to the token endpoint need to contain the exact same client ID as was used to redirect the user to the authorize endpoint. - -Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is: - -``` -grant_type=authorization_code& -code=12345& -client_id=https%3A%2F%2Fhass-auth-demo.glitch.me -``` - -The return response will be an access and refresh token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "refresh_token": "IJKLMNOPQRST", - "token_type": "Bearer" -} -``` - -The access token is a short lived token that can be used to access the API. The refresh token can be used to fetch new access tokens. The `expires_in` value is seconds that the access token is valid. - -An HTTP status code of 400 will be returned if an invalid request has been issued. The HTTP status code will be 403 if a token is requested for an inactive user. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Refresh token - -Once you have retrieved a refresh token via the grant type `authorization_code`, you can use it to fetch new access tokens. The request body is: - -``` -grant_type=refresh_token& -refresh_token=IJKLMNOPQRST& -client_id=https%3A%2F%2Fhass-auth-demo.glitch.me -``` - -The return response will be an access token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "token_type": "Bearer" -} -``` - -An HTTP status code of 400 will be returned if an invalid request has been issued. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Revoking a refresh token - -> client_id is not need for revoke refresh token - -The token endpoint is also capable of revoking a refresh token. Revoking a refresh token will immediately revoke the refresh token and all access tokens that it has ever granted. To revoke a refresh token, make the following request: - -``` -token=IJKLMNOPQRST& -action=revoke -``` - -The request will always respond with an empty body and HTTP status 200, regardless if the request was successful. - -## Long-lived access token - -A long-lived access token is usually used for 3rd party API calls and webhook-ish integrations. To generate a long-lived access token, an active websocket connection has to be established. - -Send websocket command `auth/long_lived_access_token` will create a long-lived access token for current user. Access token will not be saved in Home Assistant. User need to record the token in secure place. - -```json -{ - "id": 11, - "type": "auth/long_lived_access_token", - "client_name": "GPS Logger", - "client_icon": null, - "lifespan": 365 -} -``` - -Result will be a long-lived access token: - -```json -{ - "id": 11, - "type": "result", - "success": true, - "result": "ABCDEFGH" -} -``` - -Additionally, a long-lived access token can be created using the UI tool located at the bottom of the user's Home Assistant profile page. - -## Making authenticated requests - -Once you have an access token, you can make authenticated requests to the Home Assistant APIs. - -For the websocket connection, pass the access token in the [authentication message](https://developers.home-assistant.io/docs/en/external_api_websocket.html#authentication-phase). - -For HTTP requests, pass the token type and access token as the authorization header: - -```http -Authorization: Bearer ABCDEFGH -``` - -### Example: cURL - -```shell -curl -X GET \ - https://your.awesome.home/api/error/all \ - -H 'Authorization: Bearer ABCDEFGH' -``` - -### Example: Python - -```python -import requests - -url = "https://your.awesome.home/api/error/all" -headers = { - "Authorization": "Bearer ABCDEFGH", -} -response = requests.request("GET", url, headers=headers) - -print(response.text) -``` - -### Example: NodeJS -```JavaScript -fetch('https://your.awesome.home/api/error/all', { - headers: { Authorization: 'Bearer ABCDEFGH' } -}).then(function (response) { - if (!response.ok) { - return Promise.reject(response); - } - return response.text(); -}).then(function (body ) { - console.log(body); -}); -``` - -If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and so the user is no longer logged in. You should clear the user's data and ask the user to authorize again. - -[oauth2-spec]: https://tools.ietf.org/html/rfc6749 -[indieauth-spec]: https://indieauth.spec.indieweb.org/ -[indieauth-clients]: https://indieauth.spec.indieweb.org/#client-identifier - -## Signed paths - -Sometimes you want a user to make a GET request to Home Assistant to download data. In this case the normal auth system won't do, as we can't link the user to an API with the auth header attached to it. In that case, a signed path can help. - -A signed path is a normal path on our server, like `/api/states`, but with an attached secure authentication signature. The user is able to navigate to this path and will be authorised as the access token that created the signed path. Signed paths can be created via the websocket connection and are meant to be shortlived. The default expiration is 30 seconds. - -To get a signed path, send the following command: - -```js -{ - "type": "auth/sign_path", - "path": "/api/states", - // optional, expiration time in seconds. Defaults to 30 seconds - "expires": 20 -} -``` - -The response will contain the signed path: - -```js -{ - "path": "/api/states?authSig=ABCDEFGH" -} -``` - -Some things to note about a signed path: - - - If the refresh token is deleted, the signed url is no longer valid. - - If the user is deleted, the signed url is no longer valid (because the refresh token will be deleted). - - If Home Assistant is restarted, the signed url is no longer valid. - - Access is only validated when the request is received. If a response takes longer than the expiration time (ie, downloading a large file), the download will continue after the expiration date has passed. diff --git a/website/versioned_docs/version-0.104.0/auth_auth_provider.md b/website/versioned_docs/version-0.104.0/auth_auth_provider.md deleted file mode 100644 index aacf2651..00000000 --- a/website/versioned_docs/version-0.104.0/auth_auth_provider.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Authentication Providers -id: version-0.104.0-auth_auth_provider -original_id: auth_auth_provider ---- - -Authentication providers confirm the identity of users. The user proofs their identity by going through the login flow for an auth provider. The auth provider defines the login flow and can ask the user all information this needs. This will commonly be username and password but could also include a 2FA token or other challenges. - -Once an authentication provider has confirmed the identity of a user, it will pass that on to Home Assistant in the form of a Credentials object. - -## Defining an auth provider - -> We currently only support built-in auth providers. Support for custom auth providers might arrive in the future. - -Auth providers are defined in `homeassistant/auth/providers/.py`. The auth provider module will need to provide an implementation of the `AuthProvider` class and `LoginFlow` class, it is what asks user for information and validates it base on `data_entry_flow`. - -For an example of a fully implemented auth provider, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/providers/insecure_example.py). - -Auth providers shall extend the following methods of `AuthProvider` class. - -| method | Required | Description -| ------ | -------- | ----------- -| async def async_login_flow(self) | Yes | Return an instance of the login flow for a user to identify itself. -| async def async_get_or_create_credentials(self, flow_result) | Yes | Given the result of a login flow, return a credentials object. This can either be an existing one or a new one. -| async def async_user_meta_for_credentials(credentials) | No | Callback called Home Assistant is going to create a user from a Credentials object. Can be used to populate extra fields for the user. - -Auth providers shall extend the following methods of `LoginFlow` class. - -| method | Required | Description -| ------ | -------- | ----------- -| async def async_step_init(self, user_input=None) | Yes | Handle the login form, see more detail in below. - -## async_step_init of LoginFlow - -> We may change this inteface in near future. - -`LoginFlow` extends `data_entry_flow.FlowHandler`. The first step of data entry flow is hard coded as `init`, so each flow has to implement `async_step_init` method. The pattern of `async_step_init` likes following pseudo-code: - -```python -async def async_step_init(self, user_input=None): - if user_input is None: - return self.async_show_form( - step_id="init", data_schema="some schema to construct ui form" - ) - if is_invalid(user_input): - return self.async_show_form(step_id="init", errors=errors) - return await self.async_finish(user_input) -``` diff --git a/website/versioned_docs/version-0.104.0/auth_permissions.md b/website/versioned_docs/version-0.104.0/auth_permissions.md deleted file mode 100644 index b04e75f4..00000000 --- a/website/versioned_docs/version-0.104.0/auth_permissions.md +++ /dev/null @@ -1,278 +0,0 @@ ---- -title: Permissions -id: version-0.104.0-auth_permissions -original_id: auth_permissions ---- - -> This is an experimental feature that is not enabled or enforced yet - -Permissions limit the things a user has access to or can control. Permissions are attached to groups, of which a user can be a member. The combined permissions of all groups a user is a member of decides what a user can and cannot see or control. - -Permissions do not apply to the user that is flagged as "owner". This user will always have access to everything. - -## General permission structure - -Policies are dictionaries that at the root level consist of different categories of permissions. In the current implementation this is limited to just entities. - -```python -{ - "entities": { - # … - } -} -``` - -Each category can further split into subcategories that describe parts of that category. - -```python -{ - "entities": { - "domains": { - # … - }, - "entity_ids": { - # … - }, - } -} -``` - -If a category is omitted, the user will not have permission to that category. - -When defining a policy, any dictionary value at any place can be replaced with `True` or `None`. `True` means that permission is granted and `None` means use default, which is deny access. - -## Entities - -Entity permissions can be set on a per entity and per domain basis using the subcategories `entity_ids`, `device_ids`, `area_ids` and `domains`. You can either grant all access by setting the value to `True`, or you can specify each entity individually using the "read", "control", "edit" permissions. - -The system will return the first matching result, based on the order: `entity_ids`, `device_ids`, `area_ids`, `domains`, `all`. - -```json -{ - "entities": { - "domains": { - "switch": true - }, - "entity_ids": { - "light.kitchen": { - "read": true, - "control": true - } - } - } -} -``` - -## Merging policies - -If a user is a member of multiple groups, the groups permission policies will be combined into a single policy at runtime. When merging policies, we will look at each level of the dictionary and compare the values for each source using the following methodology: - -1. If any of the values is `True`, the merged value becomes `True`. -2. If any value is a dictionary, the merged value becomes a dictionary created by recursively checking each value using this methodology. -3. If all values are `None`, the merged value becomes `None`. - -Let's look at an example: - -```python -{ - "entities": { - "entity_ids": { - "light.kitchen": True - } - } -} -``` - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -Once merged becomes - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -## Checking permissions - -We currently have two different permission checks: can the user do the read/control/edit operation on an entity, and is the user an admin and thus allowed to change this configuration setting. - -Certain APIs will always be accessible to all users, but might offer a limited scope based on the permissions, like rendering a template. - -### Checking permissions - -To check a permission, you will need to have access to the user object. Once you have the user object, checking the permission is easy. - -```python -from homeassistant.exceptions import Unauthorized -from homeasistant.permissions.const import POLICY_READ, POLICY_CONTROL, POLICY_EDIT - -# Raise error if user is not an admin -if not user.is_admin: - raise Unauthorized() - - -# Raise error if user does not have access to control an entity -# Available policies: POLICY_READ, POLICY_CONTROL, POLICY_EDIT -if not user.permissions.check_entity(entity_id, POLICY_CONTROL): - raise Unauthorized() -``` - -### The context object - -All service calls, fired events and states in Home Assistant have a context object. This object allows us to attribute changes to events and services. These context objects also contain a user id, which is used for checking the permissions. - -It's crucial for permission checking that actions taken on behalf of the user are done with a context containing the user ID. If you are in a service handler, you should re-use the incoming context `call.context`. If you are inside a WebSocket API or Rest API endpoint, you should create a context with the correct user: - -```python -from homeassistant.core import Context - -await hass.services.async_call( - "homeassistant", "stop", context=Context(user_id=user.id), blocking=True -) -``` - -### If a permission check fails - -When you detect an anauthorized action, you should raise the `homeassistant.exceptions.Unauthorized` exception. This exception will cancel the current action and notifies the user that their action is unauthorized. - -The `Unauthorized` exception has various parameters, to identify the permission check that failed. All fields are optional. - -| # Not all actions have an ID (like adding config entry) -| # We then use this fallback to know what category was unauth - - -| Parameter | Description -| --------- | ----------- -| context | The context of the current call. -| user_id | The user ID that we tried to operate on. -| entity_id | The entity ID that we tried to operate on. -| config_entry_id | The config entry ID that we tried to operate on. -| perm_category | The permission category that we tested. Only necessary if we don't have an object ID that the user tried to operate on (like when we create a config entry). -| permission | The permission that we tested, ie `POLICY_READ`. - -### Securing a service call handler - -Service calls allow a user to control entities or with the integration as a whole. A service call uses the attached context to see which user invoked the command. Because context is used, it is important that you also pass the call context to all service calls. - -All services that are registered via the entity component (`component.async_register_entity_service()`) will automatically have their permissions checked. - -#### Checking entity permissions - -Your service call handler will need to check the permissions for each entity that it will act on. - -```python -from homeassistant.exceptions import Unauthorized, UnknownUser -from homeassistant.auth.permissions.const import POLICY_CONTROL - - -async def handle_entity_service(call): - """Handle a service call.""" - entity_ids = call.data["entity_id"] - - for entity_id in entity_ids: - if call.context.user_id: - user = await hass.auth.async_get_user(call.context.user_id) - - if user is None: - raise UnknownUser( - context=call.context, - entity_id=entity_id, - permission=POLICY_CONTROL, - ) - - if not user.permissions.check_entity(entity_id, POLICY_CONTROL): - raise Unauthorized( - context=call.context, - entity_id=entity_id, - permission=POLICY_CONTROL, - ) - - # Do action on entity - - -async def async_setup(hass, config): - hass.services.async_register(DOMAIN, "my_service", handle_entity_service) - return True -``` - -#### Checking admin permission - -Starting Home Assistant 0.90, there is a special decorator to help protect -services that require admin access. - -```python -# New in Home Assistant 0.90 -async def handle_admin_service(call): - """Handle a service call.""" - # Do admin action - - -async def async_setup(hass, config): - hass.helpers.service.async_register_admin_service( - DOMAIN, "my_service", handle_admin_service, vol.Schema({}) - ) - return True -``` - -### Securing a REST API endpoint - -```python -from homeassistant.core import Context -from homeassistant.components.http.view import HomeAssistantView -from homeassistant.exceptions import Unauthorized - - -class MyView(HomeAssistantView): - """View to handle Status requests.""" - - url = "/api/my-component/my-api" - name = "api:my-component:my-api" - - async def post(self, request): - """Notify that the API is running.""" - hass = request.app["hass"] - user = request["hass_user"] - - if not user.is_admin: - raise Unauthorized() - - hass.bus.async_fire( - "my-component-api-running", context=Context(user_id=user.id) - ) - - return self.json_message("Done.") -``` - -### Securing a Websocket API endpoint - -Verifying permissions in a Websocket API endpoint can be done by accessing the -user via `connection.user`. If you need to check admin access, you can use the -built-in `@require_admin` decorator. - -```python -from homeassistant.compnents import websocket_api - - -async def async_setup(hass, config): - hass.components.websocket_api.async_register_command(websocket_create) - return True - - -@websocket_api.require_admin -@websocket_api.async_response -@websocket_api.websocket_command( - {vol.Required("type"): "my-component/my-action",} -) -async def websocket_create(hass, connection, msg): - """Create a user.""" - # Do action -``` diff --git a/website/versioned_docs/version-0.104.0/config_entries_config_flow_handler.md b/website/versioned_docs/version-0.104.0/config_entries_config_flow_handler.md deleted file mode 100644 index 7217a5e7..00000000 --- a/website/versioned_docs/version-0.104.0/config_entries_config_flow_handler.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Integration Configuration -sidebar_label: Configuration -id: version-0.104.0-config_entries_config_flow_handler -original_id: config_entries_config_flow_handler ---- - -Integrations can be set up via the user interface by adding support for a config flow to create a config entry. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like Hass.io). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -## Updating the manifest - -You need to update your integrations manifest to inform Home Assistant that your integration has a config flow. This is done by adding `config_flow: true` to your manifest ([docs](creating_integration_manifest.md#config-flow)). - -## Defining your config flow - -Config entries uses the [data flow entry framework](data_entry_flow_index.md) to define their config flows. The config flow needs to be defined in the file `config_flow.py` in your integration folder, extend `homeassistant.config_entries.ConfigFlow` and pass a `domain` key as part of inheriting `ConfigFlow`. - -```python -from homeassistant import config_entries -from .const import DOMAIN - - -class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): - """Example config flow.""" -``` - -Once you have updated your manifest and created the `config_flow.py`, you will need to run `python3 -m script.hassfest` (one time only) for Home Assistant to activate the config entry for your integration. - -## Defining steps - -Your config flow will need to define steps of your configuration flow. The docs for [Data Entry Flow](data_entry_flow_index.md) describe the different return values of a step. Here is an example on how to define the `user` step. - -```python -class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): - async def async_step_user(self, info): - if info is not None: - pass # TODO: process info - - return self.async_show_form( - step_id="user", data_schema=vol.Schema({vol.Required("password"): str}) - ) -``` - -There are a few step names reserved for system use: - -| Step name | Description | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `user` | Invoked when a user initiates a flow via the user interface. | -| `zeroconf` | Invoked if your integration has been discovered via Zeroconf/mDNS as specified [using `zeroconf` in the manifest](creating_integration_manifest.md#zeroconf). | -| `homekit` | Invoked if your integration has been discovered via HomeKit as specified [using `homekit` in the manifest](creating_integration_manifest.md#homekit). | -| `ssdp` | Invoked if your integration has been discovered via SSDP/uPnP as specified [using `ssdp` in the manifest](creating_integration_manifest.md#ssdp). | -| `discovery` | _DEPRECATED_ Invoked if your integration has been discovered by the discovery integration. | - -## Unique IDs - -A config flow can attach a unique ID to a config flow to avoid the same device being set up twice. When a unique ID is set, it will immediately abort if another flow is in progress for this unique ID. You can also quickly abort if there is already an existing config entry for this ID. Config entries will get the unique ID of the flow that creates them. - -Call inside a config flow step: - -```python -await self.async_set_unique_id(device_unique_id) -self._abort_if_unique_id_configured() -``` - -By setting a unique ID, users will have the option to ignore the discovery of your config entry. That way they won't be bothered about it anymore. - -### Unignoring - -Your configuration flow can add support to re-discovered the previously ignored entry by implementing the unignore step in the config flow. - -```python -async def async_step_unignore(self, user_input): - unique_id = user_input["unique_id"] - await self.async_set_unique_id(unique_id) - - # TODO: Discover devices and find the one that matches the unique ID. - - return self.async_show_form(…) -``` - -## Discovery steps - -When an integration is discovered, their respective discovery step is invoked with the discovery information. The step will have to check the following things: - -- Make sure there are no other instances of this config flow in progress of setting up the discovered device. This can happen if there are multiple ways of discovering that a device is on the network. -- Make sure that the device is not already set up. -- Invoking a discovery step should never result in a finished flow and a config entry. Always confirm with the user. - -## Discoverable integrations that require no authentication - -If your integration is discoverable without requiring any authentication, you'll be able to use the Discoverable Flow that is built-in. This flow offers the following features: - -- Detect if devices/services can be discovered on the network before finishing the config flow. -- Support all manifest-based discovery protocols. -- Limit to only 1 config entry. It is up to the config entry to discover all available devices. - -To get started, run `python3 -m script.scaffold config_flow_discovery` and follow the instructions. This will create all the boilerplate necessary to configure your integration using discovery. - -## Configuration via OAuth2 - -Home Assistant has built-in support for integrations that offer account linking using [the OAuth2 authorization framework](https://tools.ietf.org/html/rfc6749). To be able to leverage this, you will need to structure your Python API library in a way that allows Home Assistant to be responsible for refreshing tokens. See our [API library guide](api_lib_index.md) on how to do this. - -The built-in OAuth2 support works out of the box with locally configured client ID / secret and with the Home Assistant Cloud Account Linking service. This service allows users to link their account with a centrally managed client ID/secret. If you want your integration to be part of this service, reach out to us at [hello@home-assistant.io](mailto:hello@home-assistant.io). - -To get started, run `python3 -m script.scaffold config_flow_oauth2` and follow the instructions. This will create all the boilerplate necessary to configure your integration using OAuth2. - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` - -When the translations are merged into Home Assistant, they will be automatically uploaded to [Lokalise](https://lokalise.co/) where the translation team will help to translate them in other languages. While developing locally, you will need to run `script/translations_develop` to see changes made to `strings.json` [More info on translating Home Assistant.](internationalization_translation.md) diff --git a/website/versioned_docs/version-0.104.0/config_entries_index.md b/website/versioned_docs/version-0.104.0/config_entries_index.md deleted file mode 100644 index da228b44..00000000 --- a/website/versioned_docs/version-0.104.0/config_entries_index.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -title: Config Entries -sidebar_label: Introduction -id: version-0.104.0-config_entries_index -original_id: config_entries_index ---- - -Config Entries are configuration data that are persistently stored by Home Assistant. A config entry is created by a user via the UI. The UI flow is powered by a [config flow handler](config_entries_config_flow_handler.md) as defined by the component. Config entries can also have an extra [options flow handler](config_entries_options_flow_handler.md), also defined by the component. - -## Lifecycle - -| State | Description | -| ----- | ----------- | -| not loaded | The config entry has not been loaded. This is the initial state when a config entry is created or when Home Assistant is restarted. | -| loaded | The config entry has been loaded. | -| setup error | An error occurred when trying to set up the config entry. | -| setup retry | A dependency of the config entry was not ready yet. Home Assistant will automatically retry loading this config entry in the future. Time between attempts will automatically increase. -| migration error | The config entry had to be migrated to a newer version, but the migration failed. -| failed unload | The config entry was attempted to be unloaded, but this was either not supported or it raised an exception. - - - -G - -not loaded - -not loaded - -loaded - -loaded - -not loaded->loaded - - - -setup error - -setup error - -not loaded->setup error - - - -setup retry - -setup retry - -not loaded->setup retry - - - -migration error - -migration error - -not loaded->migration error - - - -loaded->not loaded - - - -failed unload - -failed unload - -loaded->failed unload - - - -setup error->not loaded - - - -setup retry->not loaded - - - - - - - - -## Setting up an entry - -During startup, Home Assistant first calls the [normal component setup](https://developers.home-assistant.io/docs/en/creating_component_index.html), -and then call the method `async_setup_entry(hass, entry)` for each entry. If a new Config Entry is -created at runtime, Home Assistant will also call `async_setup_entry(hass, entry)` ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L119)). - -#### For platforms - -If a component includes platforms, it will need to forward the Config Entry to the platform. This can -be done by calling the forward function on the config entry manager ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/bridge.py#L81)): - -```python -# Use `hass.async_add_job` to avoid a circular dependency between the platform and the component -hass.async_add_job(hass.config_entries.async_forward_entry_setup(config_entry, "light")) -``` - -For a platform to support config entries, it will need to add a setup entry method ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/light/hue.py#L60)): - -```python -async def async_setup_entry(hass, config_entry, async_add_devices): - """Set up entry.""" -``` - -## Unloading entries - -Components can optionally support unloading a config entry. When unloading an entry, the component needs to clean up all entities, unsubscribe any event listener and close all connections. To implement this, add `async_unload_entry(hass, entry)` to your component ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L136)). - -For each platform that you forwarded the config entry to, you will need to forward the unloading too. - -```python -await self.hass.config_entries.async_forward_entry_unload(self.config_entry, "light") -``` - -If you need to clean up resources used by an entity in a platform, have the entity implement the [`async_will_remove_from_hass`](entity_index.md#async_will_remove_from_hass) method. - -## Removal of entries - -If a component needs to clean up code when an entry is removed, it can define a removal method: - -```python -async def async_remove_entry(hass, entry) -> None: - """Handle removal of an entry.""" -``` diff --git a/website/versioned_docs/version-0.104.0/config_entries_options_flow_handler.md b/website/versioned_docs/version-0.104.0/config_entries_options_flow_handler.md deleted file mode 100644 index 8b222a55..00000000 --- a/website/versioned_docs/version-0.104.0/config_entries_options_flow_handler.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Integration Configuration Options -sidebar_label: Configuration Options -id: version-0.104.0-config_entries_options_flow_handler -original_id: config_entries_options_flow_handler ---- - -An integration that is configured via a config entry can expose options to the user to allow tweaking behavior of the integration, like which devices or locations should be integrated. - -Config Entry Options uses the [Data Flow Entry framework](data_entry_flow_index.md) to allow users to update a config entries options. Components that want to support config entry options will need to define an Options Flow Handler. - -## Options support - -For an integration to support options it needs to have an `async_get_options_flow` method in its config flow handler. Calling it will return an instance of the components options flow handler. - -```python -@staticmethod -@callback -def async_get_options_flow(config_entry): - return OptionsFlowHandler() -``` - -## Flow handler - -The Flow handler works just like the config flow handler, except that the first step in the flow will always be `async_step_init`. - -```python -class OptionsFlowHandler(config_entries.OptionsFlow): - async def async_step_init(self, user_input=None): - """Manage the options.""" - if user_input is not None: - return self.async_create_entry(title="", data=user_input) - - return self.async_show_form( - step_id="init", - data_schema=vol.Schema( - { - vol.Required( - "show_things", - default=self.config_entry.options.get("show_things"), - ): bool - } - ), - ) -``` - -## Signal updates - -If the component should act on updated options, you can register an update listener to the config entry that will be called when the entry is updated. - -```python -entry.add_update_listener(update_listener) -``` - -The Listener shall be an async function that takes the same input as async_setup_entry. Options can then be accessed from `entry.options`. - -```python -async def update_listener(hass, entry): - """Handle options update.""" -``` diff --git a/website/versioned_docs/version-0.104.0/configuration_yaml_index.md b/website/versioned_docs/version-0.104.0/configuration_yaml_index.md deleted file mode 100644 index 7d0172bb..00000000 --- a/website/versioned_docs/version-0.104.0/configuration_yaml_index.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Integration Configuration via YAML -id: version-0.104.0-configuration_yaml_index -original_id: configuration_yaml_index ---- - -`configuration.yaml` is a configuration file defined by the user. It is automatically created by Home Assistant on first launch. It defines which components to load. - -## Pre-processing - -Home Assistant will do some pre-processing on the config based on the components that are specified to load. - -### CONFIG_SCHEMA - -If a component defines a variable `CONFIG_SCHEMA`, the config object that is passed in will be the result of running the config through `CONFIG_SCHEMA`. `CONFIG_SCHEMA` should be a voluptuous schema. - -### PLATFORM_SCHEMA - -If a component defines a variable `PLATFORM_SCHEMA`, the component will be treated as an entity component. The configuration of entity components is a list of platform configurations. - -Home Assistant will gather all platform configurations for this component. It will do so by looking for configuration entries under the domain of the component (ie `light`) but also under any entry of domain + extra text. - -While gathering the platform configs, Home Assistant will validate them. It will see if the platform exists and if the platform defines a PLATFORM_SCHEMA, validate against that schema. If not defined, it will validate the config against the PLATFORM_SCHEMA defined in the component. Any configuration that references non existing platforms or contains invalid config will be removed. - -The following `configuration.yaml`: - -```yaml -unrelated_component: - some_key: some_value - -switch: - platform: example1 - -switch living room: - - platform: example2 - some_config: true - - platform: invalid_platform -``` - -will be passed to the component as - -```python -{ - "unrelated_component": { - "some_key": "some_value" - }, - "switch": [ - { - "platform": "example1" - }, - { - "platform": "example2", - "some_config": True - } - ], -} -``` diff --git a/website/versioned_docs/version-0.104.0/creating_component_code_review.md b/website/versioned_docs/version-0.104.0/creating_component_code_review.md deleted file mode 100644 index baad718c..00000000 --- a/website/versioned_docs/version-0.104.0/creating_component_code_review.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Checklist for creating a component -sidebar_label: Component Checklist -id: version-0.104.0-creating_component_code_review -original_id: creating_component_code_review ---- - -A checklist of things to do when you're adding a new component. - -> Not all existing code follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on components level - -### 1. Requirements - - 1. Requirements have been added to [`manifest.json`](creating_integration_manifest.md). The `REQUIREMENTS` constant is deprecated. - 2. Requirement version should be pinned: `"requirements": ['phue==0.8.1']` - 3. We no longer want requirements hosted on GitHub. Please upload to PyPi. - -### 2. Configuration - - 1. Voluptuous schema present for [configuration validation](development_validation.md) - 2. Default parameters specified in voluptuous schema, not in `setup(…)` - 3. Schema using as many generic config keys as possible from `homeassistant.const` - 4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`. - 5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation` - 6. Never depend on users adding things to `customize` to configure behavior inside your component. - -### 3. Component/platform communication - - 1. You can share data with your platforms by leveraging `hass.data[DOMAIN]`. - 2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`. - -### 4. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - - ```python - # bad - status = requests.get(url("/status")) - # good - from phue import Bridge - - bridge = Bridge(...) - status = bridge.status() - ``` - - [Tutorial on publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) - -### 5. Make your pull request as small as possible - -Keep a new integration to the minimum functionality needed for someone to get value out of the integration. This allows reviewers to sign off on smaller chunks of code one at a time, and lets us get your new integration/features in sooner. **Pull requests containing large code dumps will not be a priority for review and may be closed.** - -- Limit to a single platform -- Do not add features not needed to directly support the single platform (such as custom services) -- Do not mix clean-ups and new features in a single pull request. -- Do not solve several issues in a single pull request. -- Do not submit pull requests that depend on other work which is still unmerged. - -### 6. Event names -Prefix component event names with the domain name. For example, use `netatmo_person` instead of `person` for the `netatmo` component. - -### 7. Tests - -Strongly consider adding tests for your component to minimize future regressions. diff --git a/website/versioned_docs/version-0.104.0/creating_component_index.md b/website/versioned_docs/version-0.104.0/creating_component_index.md deleted file mode 100644 index 34bff438..00000000 --- a/website/versioned_docs/version-0.104.0/creating_component_index.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Creating your first integration -id: version-0.104.0-creating_component_index -original_id: creating_component_index ---- - -Alright, you learned about the [manifest](creating_integration_manifest.md), so it's time to write your first code for your integration. AWESOME. Don't worry, we've tried hard to keep it as easy as possible. From a Home Assistant development environment, type the following and follow the instructions: - -```shell -python3 -m script.scaffold integration -``` - -This will set you up with everything that you need to build an integration that is able to be set up via the user interface. More extensive examples of integrations are available from [our example repository](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/). - -## The minimum - -The scaffold integration contains a bit more than just the bare minimum. The minimum is that you define a `DOMAIN` constant that contains the domain of the integration. The second part is that it needs to define a setup method that returns a boolean if the set up was successful. - -```python -DOMAIN = "hello_state" - - -def setup(hass, config): - hass.states.set("hello_state.world", "Paulus") - - # Return boolean to indicate that initialization was successful. - return True -``` - -And if you prefer an async component: - -```python -DOMAIN = "hello_state" - - -async def async_setup(hass, config): - hass.states.async_set("hello_state.world", "Paulus") - - # Return boolean to indicate that initialization was successful. - return True -``` - -To load this, add `hello_state:` to your `configuration.yaml` file and create a file `/custom_components/hello_state/__init__.py` with one of the two codeblocks above to test it locally. - -## What the scaffold offers - -When using the scaffold script, it will go past the bare minimum of an integration. It will include a config flow, tests for the config flow and basic translation infrastructure to provide internationalization for your config flow. diff --git a/website/versioned_docs/version-0.104.0/creating_integration_manifest.md b/website/versioned_docs/version-0.104.0/creating_integration_manifest.md deleted file mode 100644 index d2e4d3e3..00000000 --- a/website/versioned_docs/version-0.104.0/creating_integration_manifest.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -title: Integration Manifest -sidebar_label: Manifest -id: version-0.104.0-creating_integration_manifest -original_id: creating_integration_manifest ---- - -Since 0.92.0, every integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, except for custom components. - -```json -{ - "domain": "hue", - "name": "Philips Hue", - "documentation": "https://www.home-assistant.io/components/hue", - "dependencies": ["mqtt"], - "codeowners": ["@balloob"], - "requirements": ["aiohue==1.9.1"], - "quality_scale": "platinum" -} -``` - -Or a minimal example that you can copy into your project: - -```json -{ - "domain": "your_domain_name", - "name": "Your Integration", - "documentation": "https://www.example.com", - "dependencies": [], - "codeowners": [], - "requirements": [] -} -``` - -## Domain - -The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. - -## Name - -The name of the integration. - -## Documentation - -The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/` - -## Dependencies - -Dependencies are other Home Assistant integrations that you want Home Assistant to set up successfully prior to the integration being loaded. This can be necessary in case you want to offer functionality from that other integration, like using webhooks or an MQTT connection. - -## Code Owners - -GitHub usernames or team names of people that are responsible for this integration. You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included. - -## Config Flow - -Specify the `config_flow` key if your integration has a config flow to create a config entry. When specified, the file `config_flow.py` needs to exist in your integration. - -```json5 -{ - "config_flow": true -} -``` - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you are running in a virtual environment. This will make sure that all requirements are present at startup. If steps fail, like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is an array of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v3.2.0: `["pychromecast==3.2.0"]`. - -### Custom requirements during development & testing - -During the development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using `pychromecast` as an example: - -```shell -pip install pychromecast==3.2.0 --target ~/.homeassistant/deps -hass --skip-pip -``` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is specified in `requirements`. - -If you need to make changes to a requirement to support your component, it's also possible to install a development version of the requirement using `pip install -e`: - -```shell -git clone https://github.com/balloob/pychromecast.git -pip install -e ./pychromecast -hass --skip-pip -``` - -## Zeroconf - -If your integration supports discovery via [Zeroconf](https://en.wikipedia.org/wiki/Zero-configuration_networking), you can add the type to your manifest. If the user has the `zeroconf` integration loaded, it will load the `zeroconf` step of your integration's config flow when it is discovered. - -```json5 -{ - "zeroconf": ["_googlecast._tcp.local."] -} -``` - -## SSDP - -If your integration supports discovery via [SSDP](https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol), you can add the type to your manifest. If the user has the `ssdp` integration loaded, it will load the `ssdp` step of your integration's config flow when it is discovered. We support SSDP discovery by ST, and all data in UPnP device description. The manifest value is a list of matcher dictionaries, your integration is discovered if all items of any of the specified matchers are found in the SSDP/UPnP data. It's up to your config flow to filter out duplicates. - -The following example has one matcher consisting of three items, all of which must match for discovery to happen by this config. - -```json5 -{ - "ssdp": [ - { - "st": "roku:ecp", - "manufacturer": "Roku", - "deviceType": "urn:roku-com:device:player:1-0" - } - ] -} -``` - -## HomeKit - -If your integration supports discovery via HomeKit, you can add the supported model names to your manifest. If the user has the `zeroconf` integration loaded, it will load the `homekit` step of your integration's config flow when it is discovered. - -HomeKit discovery works by testing if the discovered modelname starts with any of the model names specified in the manifest.json. - -```json5 -{ - "homekit": { - "models": [ - "LIFX" - ] - } -} -``` - -Discovery via HomeKit does not mean that you have to talk the HomeKit protocol to communicate with your device. You can communicate with the device however you see fit. - -When a discovery info is routed to your integration because of this entry in your manifest, the discovery info is no longer routed to integrations that listen to the HomeKit zeroconf type. - -## Integration Quality Scale - -The [Integration Quality Scale](https://www.home-assistant.io/docs/quality_scale/) scores an integration on the code quality and user experience. Each level of the quality scale consists of a list of requirements. If an integration matches all requirements, it's considered to have reached that level. - -When your integration has no score, then don't add it to the manifest of your integration. However, be sure to look at the [Integration Quality Scale](https://www.home-assistant.io/docs/quality_scale/) list of requirements. It helps to improve the code and user experience tremendously. - -We highly recommend getting your integration scored. - -```json5 -{ - "quality_scale": "silver" -} -``` diff --git a/website/versioned_docs/version-0.104.0/creating_platform_code_review.md b/website/versioned_docs/version-0.104.0/creating_platform_code_review.md deleted file mode 100644 index ab06a3fd..00000000 --- a/website/versioned_docs/version-0.104.0/creating_platform_code_review.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Checklist for creating a platform -sidebar_label: Platform Checklist -id: version-0.104.0-creating_platform_code_review -original_id: creating_platform_code_review ---- - -A checklist of things to do when you're adding a new platform. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on platform level - * Use `CONF_MONITORED_CONDITIONS` instead of `CONF_MONITORED_VARIABLES` - -### 1. Requirements - - 1. Requirements have been added to [`manifest.json`](creating_integration_manifest.md). The `REQUIREMENTS` constant is deprecated. - 2. Requirement version should be pinned: `"requirements": ['phue==0.8.1']` - 3. We no longer want requirements hosted on GitHub. Please upload to PyPi. - -### 2. Configuration - - 1. If the platform can be set up directly, add a voluptuous schema for [configuration validation](development_validation.md) - 2. Voluptuous schema extends schema from component
(e.g., `hue.light.PLATFORM_SCHEMA` extends `light.PLATFORM_SCHEMA`) - 3. Default parameters specified in voluptuous schema, not in `setup_platform(...)` - 4. Your `PLATFORM_SCHEMA` should use as many generic config keys as possible from `homeassistant.const` - 5. Never depend on users adding things to `customize` to configure behavior inside your platform. - -```python -import voluptuous as vol - -from homeassistant.const import CONF_FILENAME, CONF_HOST -from homeassistant.components.light import PLATFORM_SCHEMA -import homeassistant.helpers.config_validation as cv - -CONF_ALLOW_UNREACHABLE = "allow_unreachable" -DEFAULT_UNREACHABLE = False - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_ALLOW_UNREACHABLE, default=DEFAULT_UNREACHABLE): cv.boolean, - vol.Optional(CONF_FILENAME): cv.string, - } -) -``` - -### 3. Setup Platform - - 1. Verify that the passed in configuration (user/pass/host etc.) works. - 2. Group your calls to `add_devices` if possible. - 3. If the platform adds extra services, the format should be `.`. So if your integration's domain is "awesome_sauce" and you are making a light platform, you would register services under the `awesome_sauce` domain. Make sure that your services [verify permissions](auth_permissions.md#checking-permissions). - -### 4. Entity - - 1. Extend the entity from the integration you're building a platform for. - - ```python - from homeassistant.components.light import Light - - - class HueLight(Light): - """Hue light component.""" - ``` - - 2. Avoid passing in `hass` as a parameter to the entity. When the entity has been added to Home Assistant, `hass` will be set on the entity when the entity is added to Home Assistant. This means you can access `hass` as `self.hass` inside the entity. - 3. Do not call `update()` in constructor, use `add_entities(devices, True)` instead. - 4. Do not do any I/O inside properties. Cache values inside `update()` instead. - 5. When dealing with time, state and/or attributes should not contain relative time since something happened. Instead, it should store UTC timestamps. - 6. Leverage the [entity lifecycle callbacks](entity_index.md#lifecycle-hooks) to attach event listeners or clean up connections. - -### 5. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - - ```python - # bad - status = requests.get(url("/status")) - # good - from phue import Bridge - - bridge = Bridge(...) - status = bridge.status() - ``` - - [Tutorial on publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) diff --git a/website/versioned_docs/version-0.104.0/data_entry_flow_index.md b/website/versioned_docs/version-0.104.0/data_entry_flow_index.md deleted file mode 100644 index 3e4a7ccb..00000000 --- a/website/versioned_docs/version-0.104.0/data_entry_flow_index.md +++ /dev/null @@ -1,279 +0,0 @@ ---- -title: Data Entry Flow -sidebar_label: Introduction -id: version-0.104.0-data_entry_flow_index -original_id: data_entry_flow_index ---- - -Data Entry Flow is a data entry framework that is part of Home Assistant. Data entry is done via data entry flows. A flow can represent a simple login form or a multi-step setup wizard for a component. A Flow Manager manages all flows that are in progress and handles creation of new flows. - -Data Entry Flow is used in Home Assistant to create config entries. - -## Flow Manager - -This is the class that manages the flows that are in progress. When instantiating one, you pass in two async callbacks: - -```python -async def async_create_flow(handler, context=context, data=data): - """Create flow.""" -``` - -The manager delegates instantiating of config flow handlers to this async callback. This allows the parent of the manager to define their own way of finding handlers and preparing a handler for instantiation. For example, in the case of the config entry manager, it will make sure that the dependencies and requirements are setup. - -```python -async def async_finish_flow(flow, result): - """Finish flow.""" -``` - -This async callback is called when a flow is finished or aborted. i.e. `result['type'] in [RESULT_TYPE_CREATE_ENTRY, RESULT_TYPE_ABORT]`. The callback function can modify result and return it back, if the result type changed to `RESULT_TYPE_FORM`, the flow will continue running, display another form. - -If the result type is `RESULT_TYPE_FORM`, the result should look like: -```python -{ - # The result type of the flow - "type": RESULT_TYPE_FORM, - # the id of the flow - "flow_id": "abcdfgh1234", - # handler name - "handler": "hue", - # name of the step, flow.async_step_[step_id] will be called when form submitted - "step_id": "init", - # a voluptuous schema to build and validate user input - "data_schema": vol.Schema(), - # an errors dict, None if no errors - "errors": errors, - # a detail information about the step - "description_placeholders": description_placeholders, -} -``` - -If the result type is `RESULT_TYPE_CREATE_ENTRY`, the result should look like: -```python -{ - # Data schema version of the entry - "version": 2, - # The result type of the flow - "type": RESULT_TYPE_CREATE_ENTRY, - # the id of the flow - "flow_id": "abcdfgh1234", - # handler name - "handler": "hue", - # title and data as created by the handler - "title": "Some title", - "result": { - "some": "data" - }, -} -``` - -If the result type is `RESULT_TYPE_ABORT`, the result should look like: -```python -{ - # The result type of the flow - "type": RESULT_TYPE_ABORT, - # the id of the flow - "flow_id": "abcdfgh1234", - # handler name - "handler": "hue", - # the abort reason - "reason": "already_configured", -} -``` - - -## Flow Handler - -Flow handlers will handle a single flow. A flow contains one or more steps. When a flow is instantiated, the `FlowHandler.init_step` step will be called. Each step has three different possible results: "Show Form", "Abort" and "Create Entry". - -At a minimum, each flow handler will have to define a version number and a step. This doesn't have to be `init`, as `async_create_flow` can assign `init_step` dependent on the current workflow, for example in configuration, `context.source` will be used as `init_step`. - -The bare minimum config flow: - -```python -from homeassistant import data_entry_flow - - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - # The schema version of the entries that it creates - # Home Assistant will call your migrate method if the version changes - # (this is not implemented yet) - VERSION = 1 - - async def async_step_user(self, user_input=None): - """Handle user step.""" -``` - -### Show Form - -This result type will show a form to the user to fill in. You define the current step, the schema of the data (using voluptuous) and optionally a dictionary of errors. Title and description of the step will be provided via the translation file. Where this is defined depends on the context of the data entry flow. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - async def async_step_user(self, user_input=None): - # Specify items in the order they are to be displayed in the UI - data_schema = { - vol.Required("username"): str, - vol.Required("password"): str, - } - - return self.async_show_form(step_id="init", data_schema=vol.Schema(data_schema)) -``` - -After the user has filled in the form, the step method will be called again and the user input is passed in. Your step will only be called if the user input passes your data schema. When the user passes in data, you will have to do extra validation of the data. For example, you can verify that the passed in username and password are valid. - -If something is wrong, you can return a dictionary with errors. Each key in the error dictionary refers to a field name that contains the error. Use the key `base` if you want to show an error unrelated to a specific field. The specified errors need to refer to a key in a translation file. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - async def async_step_user(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # See next section on create entry usage - return self.create_entry(...) - - errors["base"] = "auth_error" - - # Specify items in the order they are to be displayed in the UI - data_schema = { - vol.Required("username"): str, - vol.Required("password"): str, - } - - return self.async_show_form( - step_id="init", data_schema=vol.Schema(data_schema), errors=errors - ) -``` - -#### Multi-step flows - -If the user input passes validation, you can again return one of the three return values. If you want to navigate the user to the next step, return the return value of that step: - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - async def async_step_init(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # Store info to use in next step - self.init_info = user_input - # Return the form of the next step - return await self.async_step_account() - - ... -``` - -### Create Entry - -When the result is "Create Entry", an entry will be created and passed to the parent of the flow manager. A success message is shown to the user and the flow is finished. You create an entry by passing a title and data. The title can be used in the UI to indicate to the user which entry it is. Data can be any data type, as long as it is JSON serializable. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - async def async_step_user(self, user_input=None): - return self.create_entry( - title="Title of the entry", - data={ - "something_special": user_input["username"] - }, - ) -``` - -### Abort - -When a flow cannot be finished, you need to abort it. This will finish the flow and inform the user that the flow has finished. Reasons for a flow to not be able to finish can be that a device is already configured or not compatible with Home Assistant. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - async def async_step_user(self, user_input=None): - return self.async_abort(reason="not_supported") -``` - -### External Step & External Step Done - -It is possible that a user needs to finish a config flow by doing actions on an external website. For example, setting up an integration by being redirected to an external webpage. This is commonly used by integrations that use OAuth2 to authorize a user. - -_The example is about config entries, but works with other parts that use data entry flows too._ - -The flow works as follows: - - 1. User starts config flow in Home Assistant - 2. Config flow prompts user to finish the flow on an external website - 3. User opens the external website - 4. Upon completion of the external step, the user's browser will be redirected to a Home Assistant endpoint to deliver the response. - 5. The endpoint validates the response, and upon validation, marks the external step as done and returns JavaScript code to close the window: ``. - - To be able to route the result of the external step to the Home Assistant endpoint, you will need to make sure the config flow ID is included. If your external step is an OAuth2 flow, you can leverage the oauth2 state for this. This is a variable that is not interpreted by the authorization page but is passed as-is to the Home Assistant endpoint. - 6. The window closes and the Home Assistant user interface with the config flow will be visible to the user again. - 7. The config flow has automatically advanced to the next step when the external step was marked as done. The user is prompted with the next step. - -Example configuration flow that includes an external step. - -```python -from homeassistant import config_entries - - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - VERSION = 1 - data = None - - async def async_step_user(self, user_input=None): - if not user_input: - return self.async_external_step( - step_id="user", - url=f"https://example.com/?config_flow_id={self.flow_id}", - ) - - self.data = user_input - return self.async_external_step_done(next_step_id="finish") - - async def async_step_finish(self, user_input=None): - return self.async_create_entry(title=self.data["title"], data=self.data) -``` - -Avoid doing work based on the external step data before you return an `async_mark_external_step_done`. Instead, do the work in the step that you refer to as `next_step_id` when marking the external step done. This will give the user a better user experience by showing a spinner in the UI while the work is done. - -If you do the work inside the authorize callback, the user will stare at a blank screen until that all of a sudden closes because the data has forwarded. If you do the work before marking the external step as done, the user will still see the form with the "Open external website" button while the background work is being done. That too is undesirable. - -Example code to mark an external step as done: - -```python -from homeassistant import data_entry_flow - - -async def handle_result(hass, flow_id, data): - result = await hass.config_entries.async_configure(flow_id, data) - - if result["type"] == data_entry_flow.RESULT_TYPE_EXTERNAL_STEP_DONE: - return "success!" - else: - return "Invalid config flow specified" -``` - -## Translations - -Data entry flows depend on translations for showing the text in the forms. It depends on the parent of a data entry flow manager where this is stored. - -## Initializing a config flow from an external source - -You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing a flow: - -```python -await flow_mgr.async_init( - "hue", context={"source": data_entry_flow.SOURCE_DISCOVERY}, data=discovery_info -) -``` - -The config flow handler will not start with the `init` step. Instead, it will be instantiated with a step name equal to the source. The step should follow the same return values as a normal step. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - async def async_step_discovery(self, info): - """Handle discovery info.""" -``` diff --git a/website/versioned_docs/version-0.104.0/dev_101_config.md b/website/versioned_docs/version-0.104.0/dev_101_config.md deleted file mode 100644 index 7e8dd9dc..00000000 --- a/website/versioned_docs/version-0.104.0/dev_101_config.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Using Config -id: version-0.104.0-dev_101_config -original_id: dev_101_config ---- - -Based on where you are in the code, `config` can mean various things. - -### On the hass object - -On the hass object it is an instance of the Config class. The Config class contains the users preferred units, the path to the config directory and which components are loaded. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config) - -### Config passed into component setup - -The `config` parameter passed to a component setup is a dictionary containing all of the user supplied configuration. The keys of the dictionary are the component names and the value is another dictionary with the component configuration. - -The object will have already been validated using your `CONFIG_SCHEMA` or `PLATFORM_SCHEMA` if available. If you have defined a `PLATFORM_SCHEMA`, all references to your component (ie `light 2:` etc) will have been changed to be accessible as a list under `config[DOMAIN]`. - -If your configuration file contains the following lines: - -```yaml -example: - host: paulusschoutsen.nl -``` - -Then in the setup method of your component you will be able to refer to `config['example']['host']` to get the value `paulusschoutsen.nl`. - -### Passed into platform setup - -The `config` parameter passed to a platform setup function is only the config for that specific platform. diff --git a/website/versioned_docs/version-0.104.0/dev_101_events.md b/website/versioned_docs/version-0.104.0/dev_101_events.md deleted file mode 100644 index 78d93c19..00000000 --- a/website/versioned_docs/version-0.104.0/dev_101_events.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Using Events -id: version-0.104.0-dev_101_events -original_id: dev_101_events ---- - -The core of Home Assistant is driven by events. That means that if you want to respond to something happening, you'll have to respond to events. Most of the times you won't interact directly with the event system but use one of the [event listener helpers][helpers]. - -The event system is very flexible. There are no limitations on the event type, as long as it's a string. Each event can contain data. The data is a dictionary that can contain any data as long as it's JSON serializable. This means that you can use number, string, dictionary and list. - -[List of events that Home Assistant fires.][object] - -## Firing events - -To fire an event, you have to interact with the event bus. The event bus is available on the Home Assistant instance as `hass.bus`. - -Example component that will fire an event when loaded. Note that custom event names are prefixed with the component name. - -```python -DOMAIN = "example_component" - - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - # Fire event example_component_my_cool_event with event data answer=42 - hass.bus.fire("example_component_my_cool_event", {"answer": 42}) - - # Return successful setup - return True -``` - -## Listening to events - -Most of the times you'll not be firing events but instead listen to events. For example, the state change of an entity is broadcasted as an event. - -```python -DOMAIN = "example_component" - - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - count = 0 - - # Listener to handle fired events - def handle_event(event): - nonlocal count - count += 1 - print(f"Answer {count} is: {event.data.get('answer')}") - - # Listen for when example_component_my_cool_event is fired - hass.bus.listen("example_component_my_cool_event", handle_event) - - # Return successful setup - return True -``` - -### Helpers - -Home Assistant comes with a lot of bundled helpers to listen to specific types of event. There are helpers to track a point in time, to track a time interval, a state change or the sun set. [See available methods.][helpers] - -[helpers]: https://dev-docs.home-assistant.io/en/master/api/helpers.html#module-homeassistant.helpers.event -[object]: https://www.home-assistant.io/docs/configuration/events/ diff --git a/website/versioned_docs/version-0.104.0/dev_101_index.md b/website/versioned_docs/version-0.104.0/dev_101_index.md deleted file mode 100644 index 19fc984b..00000000 --- a/website/versioned_docs/version-0.104.0/dev_101_index.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Development 101 -sidebar_label: Introduction -id: version-0.104.0-dev_101_index -original_id: dev_101_index ---- - -The goal of development 101 is to get you familiar with the basics of developing for Home Assistant. Before we start, please make sure you familiarize yourself with the [architecture](architecture_index.md). - -To get our code running inside Home Assistant we're going to create a custom component. The first step is to locate your config folder. You can find the path to your config folder by opening the Home Assistant frontend, click on the service developer tool icon. It's the path after the text "Path to configuration.yaml". - -Inside your configuration directory create a new folder called `custom_components`. It might be that one already exists, that's fine too. This is the folder that Home Assistant will look at when looking for custom code. - -> The Home Assistant API has two variants: a synchronous and an asynchronous version (asyncio). This development course will focus on the synchronous version. - -To verify that everything is working correctly, let's create a small Hello World component. To do so, create a file called `hello_world.py` in your custom components folder. Copy paste the following content to it: - -```python -# The domain of your component. Equal to the filename of your component. -DOMAIN = "hello_world" - - -def setup(hass, config): - """Setup the hello_world component.""" - # States are in the format DOMAIN.OBJECT_ID. - hass.states.set("hello_world.Hello_World", "Works!") - - # Return boolean to indicate that initialization was successfully. - return True -``` - -Last step is to add `hello_world:` entry to your `configuration.yaml` file. - -```yaml -# Hello World component -hello_world: -``` - -After running `hass`, we should see log entries stating that `hello_world` component was loaded. What is more, an additional state card will appear within the main panel. - -```log -2018-04-03 21:44:20 INFO (MainThread) [homeassistant.loader] Loaded hello_world from custom_components.hello_world -2018-04-03 21:44:20 INFO (MainThread) [homeassistant.setup] Setting up hello_world -``` - -State card showing that Hello World component is working as intended. diff --git a/website/versioned_docs/version-0.104.0/dev_101_services.md b/website/versioned_docs/version-0.104.0/dev_101_services.md deleted file mode 100644 index c4600de0..00000000 --- a/website/versioned_docs/version-0.104.0/dev_101_services.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Integration Services -sidebar_label: Custom Services -id: version-0.104.0-dev_101_services -original_id: dev_101_services ---- - -Home Assistant provides ready-made services for a lot of things, but it doesn't always cover everything. Instead of trying to change Home Assistant, it is preferred to add it as a service under your own integration first. Once we see a pattern in these services, we can talk about generalizing them. - -This is a simple "hello world" example to show the basics of registering a service. To use this example, create the file `/custom_components/hello_service/__init__.py` and copy the below example code. - -Services can be called from automations and from the service "Developer tools" in the frontend. - -```python -DOMAIN = "hello_service" - -ATTR_NAME = "name" -DEFAULT_NAME = "World" - - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - def handle_hello(call): - """Handle the service call.""" - name = call.data.get(ATTR_NAME, DEFAULT_NAME) - - hass.states.set("hello_service.hello", name) - - hass.services.register(DOMAIN, "hello", handle_hello) - - # Return boolean to indicate that initialization was successfully. - return True -``` - -Load the integration by adding the following to your `configuration.yaml`. When your component is loaded, a new service should be available to call. - -```yaml -# configuration.yaml entry -hello_service: -``` - -Open the frontend and in the sidebar, click the first icon in the developer tool section. This will open the Call Service developer tool. On the right, find your service and click on it. This will automatically fill in the correct values. - -Pressing "Call Service" will now call your service without any parameters. This will cause your service to create a state with the default name 'World'. If you want to specify the name, you have to specify parameters. Add the following JSON as Service Data and press "Call Service again". - -```json -{ - "name": "Planet" -} -``` - -The service will now overwrite the previous state with "Planet". - -## Service descriptions - -Adding services is only useful if users know about them. In Home Assistant we use a `services.yaml` as part of your integration to describe the services. - -Services are published under the domain name of your integration, so in `services.yaml` we only use the service name as the base key. - -```yaml -# Example services.yaml entry - -set_speed: - # Description of the service - description: Sets fan speed. - # Different fields that your service accepts - fields: - # Key of the field - entity_id: - # Description of the field - description: Name(s) of the entities to set - # Example value that can be passed for this field - example: 'fan.living_room' - speed: - description: Speed setting - example: 'low' -``` diff --git a/website/versioned_docs/version-0.104.0/dev_101_states.md b/website/versioned_docs/version-0.104.0/dev_101_states.md deleted file mode 100644 index 2a15ecf4..00000000 --- a/website/versioned_docs/version-0.104.0/dev_101_states.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Using States -id: version-0.104.0-dev_101_states -original_id: dev_101_states ---- - -Home Assistant keeps track of the states of entities in a state machine. The state machine has very few requirements: - - - Each state is related to an entity identified by an entity id. This id is made up of a domain and an object id. For example `light.kitchen_ceiling`. You can make up any combination of domain and object id, even overwriting existing states. - - Each state has a primary attribute that describes the state of the entity. In the case of a light this could be for example "on" and "off". You can store anything you want in the state, as long as it's a string (will be converted if it's not). - - You can store more information about an entity by setting attributes. Attributes is a dictionary that can contain any data that you want. The only requirement is that it's JSON serializable, so you're limited to numbers, strings, dictionaries and lists. - -[Description of the state object.](https://www.home-assistant.io/docs/configuration/state_object/) - -## Using states in your component - -This is a simple tutorial/example on how to create and set states. We will do our work in a component called "hello_state". The purpose of this component is to display a given text in the frontend. - -To get started, create the file `/custom_components/hello_state.py` and copy the below example code. - -```python -""" -Support for showing text in the frontend. - -For more details about this component, please refer to the documentation at -https://developers.home-assistant.io/docs/en/dev_101_states.html -""" -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = "hello_state" - - -def setup(hass, config): - """Setup the Hello State component. """ - _LOGGER.info("The 'hello state' component is ready!") - - return True -``` - -1. In the file header we decided to add some details: A short description and the link to the documentation. -2. We want to do some logging. This means that we import the Python logging module and create an alias. -3. The component name is equal to the domain name. -4. The `setup` function will take care of the initialization of our component. - The component will only write a log message. Keep in mind for later that you have several options for the severity: - - - `_LOGGER.info(msg)` - - `_LOGGER.warning(msg)` - - `_LOGGER.error(msg)` - - `_LOGGER.critical(msg)` - - `_LOGGER.exception(msg)` - -5. We return `True` if everything is ok. - -Add the component to your `configuration.yaml` file. - -```yaml -hello_state: -``` - -After a start or a restart of Home Assistant the component will create an entry in the log. - -```log -16-03-12 14:16:42 INFO (MainThread) [custom_components.hello_state] The 'hello state' component is ready! -``` - -The next step is the introduction of configuration options. A user can pass configuration options to our component via `configuration.yaml`. To use them we'll use the passed in `config` variable to our `setup` method. - -```python -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = "hello_state" - -CONF_TEXT = "text" -DEFAULT_TEXT = "No text!" - - -def setup(hass, config): - """Set up the Hello State component. """ - # Get the text from the configuration. Use DEFAULT_TEXT if no name is provided. - text = config[DOMAIN].get(CONF_TEXT, DEFAULT_TEXT) - - # States are in the format DOMAIN.OBJECT_ID - hass.states.set("hello_state.Hello_State", text) - - return True -``` - -To use the latest feature of our component, update the entry in your `configuration.yaml` file. - -```yaml -hello_state: - text: 'Hello, World!' -``` - -Thanks to `DEFAULT_TEXT` variable the component will launch even if no `text:` field is used in the `configuration.yaml` file. Quite often there are variables which are required. It's important to check if all mandatory configuration variables are provided. If not, the setup should fail. We will use `voluptuous` as a helper to achieve this. The next listing shows the essential parts. - -```python -import voluptuous as vol - -import homeassistant.helpers.config_validation as cv - -CONFIG_SCHEMA = vol.Schema( - {DOMAIN: vol.Schema({vol.Required(CONF_TEXT): cv.string,})}, extra=vol.ALLOW_EXTRA -) -``` - -Now, when `text:` is missing from the config, Home Assistant will alert the user and not setup your component. - -After a start or a restart of Home Assistant the component will be visible in the frontend if the `configuration.yaml` file is up-to-date. - -

- -

- -In order to expose attributes for a platform, you will need to define a property called `device_state_attributes` on the entity class, which will return a dictionary of attributes: - -```python -@property -def device_state_attributes(self): - """Return device specific state attributes.""" - return self._attributes -``` - -> Entities also have a similar property `state_attributes`, which normally doesn't need to be defined by new platforms. This property is used by base components to add standard sets of attributes to a state. Example: The light component uses `state_attributes` to add brightness to the state dictionary. If you are designing a new component, you should define `state_attributes` instead. - -To get your component included in the Home Assistant releases, follow the steps described in the [Submit your work](development_submitting.md) section. Basically you only need to move your component into the `homeassistant/component/` directory of your fork and create a Pull Request. diff --git a/website/versioned_docs/version-0.104.0/development_catching_up.md b/website/versioned_docs/version-0.104.0/development_catching_up.md deleted file mode 100644 index 4d82925f..00000000 --- a/website/versioned_docs/version-0.104.0/development_catching_up.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Catching up with Reality -id: version-0.104.0-development_catching_up -original_id: development_catching_up ---- - -If it's taking a while to develop your feature, and you want to catch up with what's in the current Home Assistant `dev` branch, you can use `git rebase`. This will pull the latest Home Assistant changes locally, rewind your commits, bring in the latest changes from Home Assistant, and replay all of your commits on top. - -> If you use the workflow below, it is important that you force push the update as described. Git might prompt you to do `git pull` first. Do **NOT** do that! It would mess up your commit history. - -```shell -# Run this from your feature branch -$ git fetch upstream dev # to pull the latest changes into a local dev branch -$ git rebase upstream/dev # to put those changes into your feature branch before your changes -``` - -If rebase detects conflicts, repeat this process until all changes have been resolved: - -1. `git status` shows you the file with the conflict; edit the file and resolve the lines between `<<<< | >>>>` -3. Add the modified file: `git add ` or `git add .` -4. Continue rebase: `git rebase --continue` -5. Repeat until you've resolved all conflicts - -After rebasing your branch, you will have rewritten history relative to your GitHub fork's branch. When you go to push you will see an error that your history has diverged from the original branch. In order to get your GitHub fork up-to-date with your local branch, you will need to force push, using the following command: - -```shell -# Run this from your feature branch -$ git push origin --force -``` - -Other workflows are covered in detail in the [Github documentation](https://help.github.com/articles/fork-a-repo/). Add an additional `remote` after you clone your fork. - -```shell -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -Then, `git pull --rebase upstream dev`. - diff --git a/website/versioned_docs/version-0.104.0/development_environment.md b/website/versioned_docs/version-0.104.0/development_environment.md deleted file mode 100644 index 0e1eaf9d..00000000 --- a/website/versioned_docs/version-0.104.0/development_environment.md +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.104.0-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```shell -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```shell -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev pkg-config -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example CentOS would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Since Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run - -```shell -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is set up, perform install as for Linux. - -```shell -$ sudo apt-get update -$ sudo apt-get install python3-pip python3.7-dev python3.7-venv python-wheel-common -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```shell -$ mkdir -p ../config -$ hass -c ../config -``` - -### Developing on macOS - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```shell -$ brew install python3 autoconf -``` - -Then install ffmpeg: - -```shell -$ brew install ffmpeg -``` - -### Developing with devcontainer - -The devcontainer is a preconfigured development environment with all the tools you need. - -**Prerequisites** - -- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) -- [Docker](https://docs.docker.com/install/) -- [Visual Studio code](https://code.visualstudio.com/) -- [Remote - Containers (VSC Extension)](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) - -[More info about requirements and devcontainer in general](https://code.visualstudio.com/docs/remote/containers#_getting-started) - -**Getting started:** - -1. Fork the repository. -1. Clone the repository to your computer. -1. Open the repository using Visual Studio code. - -When you open this repository with Visual Studio code you are asked to "Reopen in Container", this will start the build of the container. - -_If you don't see this notification, open the command pallet and select `Remote-Containers: Reopen Folder in Container`._ - -_If you get `command 'remote-containers.reopenInContainer' not found` make sure to use a Visual Studio code version with remote container support enabled._ - -The devcontainter comes with some useful tasks to help you with development, you can start these tasks by opening the command pallet and select `Tasks: Run Task` then select the task you want to run. - -Running tasks like `Preview` can be restarted by opening the command pallet and selecting `Tasks: Restart Running Task`, then select the task you want to restart. - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -_Windows users should be sure to clone to a path that inside the WSL (ex: ~/)._ - -```shell -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```shell -$ python3.7 -m venv venv -$ source venv/bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```shell -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```shell -$ hass -``` - -## Logging - -By default logging in Home Assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` diff --git a/website/versioned_docs/version-0.104.0/development_guidelines.md b/website/versioned_docs/version-0.104.0/development_guidelines.md deleted file mode 100644 index 0846e1c1..00000000 --- a/website/versioned_docs/version-0.104.0/development_guidelines.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: Style guidelines -id: version-0.104.0-development_guidelines -original_id: development_guidelines ---- - -Home Assistant enforces quite strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. - -We use [Black](https://github.com/psf/black) for uncompromised code formatting. Every pull request is automatically checked as part of the linting process and we never merge submissions that diverge. - -Summary of the most relevant points: - -- Comments should be full sentences and end with a period. -- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered. -- Constants and the content of lists and dictionaries should be in alphabetical order. - -It is advisable to adjust IDE or editor settings to match those requirements. - -## Our recommendations - -For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code consistent. - -### File headers - -The docstring in the file header should describe what the file is about. - -```python -"""Support for MQTT lights.""" -``` - -### Log messages - -There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. A widely used style is shown below but you are free to compose the messages as you like. - -```python -_LOGGER.error("No route to device: %s", self._resource) -``` - -```log -2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18 -``` - -Do not print out API keys, tokens, usernames or passwords (even if they are wrong). -Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` for anything else. - -### Ordering of imports - -Instead of order the imports manually, use [`isort`](https://github.com/timothycrosley/isort). - -```shell -$ pip3 install isort -$ isort homeassistant/components/sensor/fixer.py -``` - -### Use new style string formatting - -Prefer [f-strings](https://docs.python.org/3/reference/lexical_analysis.html#f-strings) over `%` or `str.format`. - -```python -# New -f"{some_value} {some_other_value}" -# Old, wrong -"{} {}".format("New", "style") -"%s %s" % ("Old", "style") -``` - -One exception is for logging which uses the percentage formatting. This is to avoid formatting the log message when it is suppressed. - -```python -_LOGGER.info("Can't connect to the webservice %s at %s", string1, string2) -``` diff --git a/website/versioned_docs/version-0.104.0/development_testing.md b/website/versioned_docs/version-0.104.0/development_testing.md deleted file mode 100644 index 85ec660f..00000000 --- a/website/versioned_docs/version-0.104.0/development_testing.md +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: Testing your code -id: version-0.104.0-development_testing -original_id: development_testing ---- - -As it states in the [Style guidelines section](development_guidelines.md) all code is checked to verify the following: - -- All the unit tests pass -- All code passes the checks from the linting tools - -Local testing is done using [Tox](https://tox.readthedocs.io), which has been installed as part of running `script/setup` in the [virtual environment](development_environment.md). To start the tests, activate the virtual environment and simply run the command: - -```shell -$ tox -``` - -It might be required that you install additional packages depending on your distribution/operating system: - -- Fedora: `sudo dnf -y install systemd-devel gcc-c++` -- Ubuntu: `sudo apt-get install libudev-dev` - -**Important:** Run `tox` before you create your pull request to avoid annoying fixes. - -Running `tox` will run unit tests against the locally available Python releases, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one `tox` target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py38` runs unit tests only on Python 3.8. - -`tox` uses virtual environments under the hood to create isolated testing environments. The `tox` virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell `tox` to recreate the virtual environments. - -macOS users may see an `Error creating virtualenv` when runnng `tox`. If this occurs, install the [tox-venv](https://pypi.org/project/tox-venv/) package using the command `pip install tox-venv` and try again. - -### Adding new dependencies to test environment - -If you are working on tests for an integeration and you need the dependencies available inside the `tox` environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments. - -### Running single tests using `tox` - -You can pass arguments via `tox` to `py.test` to be able to run single test suites or test files. Replace `py38` with the Python version that you use. - -```shell -# Stop after the first test fails -$ tox -e py38 -- tests/test_core.py -x -# Run test with specified name -$ tox -e py38 -- tests/test_core.py -k test_split_entity_id -# Fail a test after it runs for 2 seconds -$ tox -e py38 -- tests/test_core.py --timeout 2 -# Show the 10 slowest tests -$ tox -e py38 -- tests/test_core.py --duration=10 -``` - -### Testing outside of Tox - -Running `tox` will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without `tox`, you'll need to install the test dependencies into your Python environment: - -```shell -$ pip3 install -r requirements_test_all.txt -c homeassistant/package_constraints.txt -``` - -Now that you have all test dependencies installed, you can run tests on individual files: - -```shell -$ flake8 homeassistant/core.py -$ pylint homeassistant/core.py -$ pydocstyle homeassistant/core.py -$ py.test tests/test_core.py -``` - -You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script: - -```shell -$ script/lint -``` - -### Preventing linter errors - -Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them! - -```shell -$ pip3 install flake8 flake8-docstrings -$ flake8 --install-hook=git -``` - -The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8. - -### Notes on PyLint and PEP8 validation - -If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member. diff --git a/website/versioned_docs/version-0.104.0/development_validation.md b/website/versioned_docs/version-0.104.0/development_validation.md deleted file mode 100644 index 2a0e6a02..00000000 --- a/website/versioned_docs/version-0.104.0/development_validation.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: Validate the input -id: version-0.104.0-development_validation -original_id: development_validation ---- - -The `configuration.yaml` file contains the configuration options for components and platforms. We use [voluptuous](https://pypi.python.org/pypi/voluptuous) to make sure that the configuration provided by the user is valid. Some entries are optional or could be required to set up a platform or a component. Others must be a defined type or from an already-defined list. - -We test the configuration to ensure that users have a great experience and minimize notifications if something is wrong with a platform or component setup before Home Assistant runs. - -Besides [voluptuous](https://pypi.python.org/pypi/voluptuous) default types, many custom types are available. For an overview, take a look at the [config_validation.py](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/config_validation.py) helper. - -- Types: `string`, `byte`, and `boolean` -- Entity ID: `entity_id` and `entity_ids` -- Numbers: `small_float` and `positive_int` -- Time: `time`, `time_zone` -- Misc: `template`, `slug`, `temperature_unit`, `latitude`, `longitude`, `isfile`, `sun_event`, `ensure_list`, `port`, `url`, and `icon` - -To validate platforms using [MQTT](https://www.home-assistant.io/components/mqtt/), `valid_subscribe_topic` and `valid_publish_topic` are available. - -Some things to keep in mind: - -- Use the constants defined in `const.py` -- Import `PLATFORM_SCHEMA` from the integration you are integrating with and extend it. -- Preferred order is `required` first and `optional` second -- Default values for optional configuration keys need to be valid values. Don't use a default which is `None` like `vol.Optional(CONF_SOMETHING, default=None): cv.string`, set the default to `default=''` if required. - -### Snippets - -This section contains snippets for the validation we use. - -#### Default name - -It's common to set a default for a sensor if the user doesn't provide a name to use. - -```python -DEFAULT_NAME = "Sensor name" - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - # ... - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, - } -) -``` - -#### Limit the values - -You might want to limit the user's input to a couple of options. - -```python -DEFAULT_METHOD = "GET" - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - # ... - vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): vol.In(["POST", "GET"]), - } -) -``` - -#### Port - -All port numbers are from a range of 1 to 65535. - -```python -DEFAULT_PORT = 993 - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - # ... - vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, - } -) -``` - -#### Lists - -If a sensor has a pre-defined list of available options, test to make sure the configuration entry matches the list. - -```python -SENSOR_TYPES = { - "article_cache": ("Article Cache", "MB"), - "average_download_rate": ("Average Speed", "MB/s"), -} - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( - { - # ... - vol.Optional(CONF_MONITORED_VARIABLES, default=[]): vol.All( - cv.ensure_list, [vol.In(SENSOR_TYPES)] - ), - } -) -``` diff --git a/website/versioned_docs/version-0.104.0/device_registry_index.md b/website/versioned_docs/version-0.104.0/device_registry_index.md deleted file mode 100644 index 3664d56a..00000000 --- a/website/versioned_docs/version-0.104.0/device_registry_index.md +++ /dev/null @@ -1,81 +0,0 @@ ---- -title: Device Registry -sidebar_label: Introduction -id: version-0.104.0-device_registry_index -original_id: device_registry_index ---- - -The device registry is a registry where Home Assistant keeps track of devices. A device is represented in Home Assistant via one or more entities. For example, a battery-powered temperature and humidity sensor might expose entities for temperature, humidity and battery level. - -Device registry overview - -## What is a device? - -A device in Home Assistant represents a physical device that has its own control unit. The control unit itself does not have to be smart, but it should be in control of what happens. For example, an Ecobee thermostat with 4 room sensors equals 5 devices in Home Assistant, one for the thermostat including all sensors inside it, and one for each sensor. Each device exists in a specific geographical area, and may have more than one input or output within that area. - -If you connect a sensor to another device to read some of its data, it should still be represented as two different devices. The reason for this is that the sensor could be moved to read the data of another device. - -A device that offers multiple endpoints, where parts of the device sense or output in different areas, should be split into separate devices and refer back to parent device with the `via_device` attribute. This allows the separate endpoints to be assigned to different areas in the building. - -> Although not currently available, we could consider offering an option to users to merge devices. - -## Device properties - -| Attribute | Description | -| --------- | ----------- | -| id | Unique ID of device (generated by Home Assistant) -| name | Name of this device -| connections | A set of tuples of `(connection_type, connection identifier)`. Connection types are defined in the device registry module. -| identifiers | Set of identifiers. They identify the device in the outside world. An example is a serial number. -| manufacturer | The manufacturer of the device. -| model | The model of the device. -| config_entries | Config entries that are linked to this device. -| sw_version | The firmware version of the device. -| via_device | Identifier of a device that routes messages between this device and Home Assistant. Examples of such devices are hubs, or parent devices of a sub-device. This is used to show device topology in Home Assistant. -| area_id | The Area which the device is placed in. - -## Defining devices - -> Entity device info is only read if the entity is loaded via a [config entry](config_entries_index.md). - -Each entity is able to define a device via the `device_info` property. This property is read when an entity is added to Home Assistant via a config entry. A device will be matched up with an existing device via supplied identifiers and connections, like serial numbers or MAC addresses. - -```python -# Inside a platform -class HueLight(LightEntity): - @property - def device_info(self): - return { - "identifiers": { - # Serial numbers are unique identifiers within a specific domain - (hue.DOMAIN, self.unique_id) - }, - "name": self.name, - "manufacturer": self.light.manufacturername, - "model": self.light.productname, - "sw_version": self.light.swversion, - "via_device": (hue.DOMAIN, self.api.bridgeid), - } -``` - -Components are also able to register devices in the case that there are no entities representing them. An example is a hub that communicates with the lights. - -```python -# Inside a component -from homeassistant.helpers import device_registry as dr - -device_registry = await dr.async_get_registry(hass) - -device_registry.async_get_or_create( - config_entry_id=entry.entry_id, - connections={(dr.CONNECTION_NETWORK_MAC, config.mac)}, - identifiers={(DOMAIN, config.bridgeid)}, - manufacturer="Signify", - name=config.name, - model=config.modelid, - sw_version=config.swversion, -) -``` diff --git a/website/versioned_docs/version-0.104.0/documentation_create_page.md b/website/versioned_docs/version-0.104.0/documentation_create_page.md deleted file mode 100644 index 5185be19..00000000 --- a/website/versioned_docs/version-0.104.0/documentation_create_page.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Create a new page -id: version-0.104.0-documentation_create_page -original_id: documentation_create_page ---- - -For a platform or integration page, the fastest way is to make a copy of an existing page and edit it. The [Integration overview](https://www.home-assistant.io/integrations/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages. - -Please honor the [Standards](documentation_standards.md) we have for the documentation. - -If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers. - -```text ---- -title: "Awesome Sensor" -description: "home-assistant.io web presence" -ha_release: "0.38" -ha_category: Sensor -ha_iot_class: "Local Polling" -ha_quality_scale: silver -ha_config_flow: true -ha_codeowners: - - '@balloob' ---- - -Content... Written in markdown. - -### Title Header -... -``` - -Additional keys for the file header: - -- `title`: This title should match with the name of the integration as written in the integration manifest file. -- `logo`: Please check the separate section below. -- `ha_release`: The release when the integration was included, e.g., "0.38". If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `' '`. -- `ha_category`: This entry is used to group the integration on the [Integration overview](https://www.home-assistant.io/integrations/). -- `ha_iot_class`: [IoT class](https://www.home-assistant.io/blog/2016/02/12/classifying-the-internet-of-things) is the classifier for the device's behavior. -- `ha_quality_scale`: [Quality scale](https://www.home-assistant.io/docs/quality_scale/) is the representation of the integration's quality. -- `ha_config_flow`: Set to `true` if the integration has a [Data Entry Flow](https://developers.home-assistant.io/docs/en/data_entry_flow_index.html), omit otherwise. -- `ha_codeowners`: GitHub usernames or team names (starting with `@`) of people that are responsible for this integration. This should match with the codeowners as listed in the integration manifest file. - -There are [pre-defined variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation. - -A couple of points to remember: - -- Document the needed steps to retrieve API keys or access token for the third party service or device if needed. -- Add screenshots to support the user where it makes sense. -- Add the type of the device(s) (incl. firmware) you have tested when you know that there are multiple out there. - -### Configuration - -Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file. - -The **Configuration Variables** section must use the `{% configuration %} ... {% endconfiguration %}` tag. - -```text -{% configuration %} -api_key: - description: The API key to access the service. - required: true - type: string -name: - description: Name to use in the frontend. - required: false - default: The default name to use in the frontend. - type: string -monitored_conditions: - description: Conditions to display in the frontend. - required: true - type: map - keys: - weather: - description: A human-readable text summary. - temperature: - description: The current temperature. -{% endconfiguration %} -``` - -Available keys: - -- **`description:`**: That the variable is about. -- **`required:`**: If the variable is required. - -```text -required: true #=> Required -required: false #=> Optional -required: inclusive #=> Inclusive -required: exclusive #=> Exclusive -required: any string here #=> Any string here -``` - -- **`type:`**: The type of the variable. Allowed entries: `boolean`, `string`, `integer`, `float`, `time`, `template`, `device_class`, `icon` or `map`/`list` (for a list of entries). For multiple possibilities use `[string, integer]`. If you use `map`/`list` then should define `keys:` (see the [`template` sensor](https://www.home-assistant.io/components/sensor.template/) for an example). If you use `boolean`, then `default:` must be defined. -- **`default:`**: The default value for the variable. - -### Embedding Code - -You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in back-ticks. - -When you're writing code that is to be executed on the terminal, do not prefix them with `$`, since this makes it hard to copy and paste the commands. However, an exception is made when there is a need to distinguish between typed commands and command output. In those cases, prefixing the commands with a `$` is required. - -### Templates - -For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) [Jinja](http://jinja.pocoo.org/) is used. Check the [Documentation Standards](documentation_standards.md) for further details. - -If you are don't escape templates then they will be rendered and appear blank on the website. - -### HTML - -The direct usage of HTML is supported but not recommended. The note boxes are an exception. - -```html -
- You need to enable telnet on your router. -
-``` - -Please note, if you want to use Markdown inside an HTML block, it has to be surrounded by a new line. - -```html -
- - You need to enable [**telnet**](https://en.wikipedia.org/wiki/Telnet) on your router. - -
-``` - -### Images, icons and logos - -The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent. - -| Type | Location | -| :---------- | :----------------------------- | -| logos | source/images/supported_brands | -| blog | source/images/blog | -| screenshots | source/images/components | - -Not everything (product, integration, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/). - -### Linking From The Sidebar - -If you are adding a new page that requires linking from the sidebar, you need to edit the `docs_navigation.html` file in `source/_includes/asides/docs_navigation.html`. diff --git a/website/versioned_docs/version-0.104.0/documentation_index.md b/website/versioned_docs/version-0.104.0/documentation_index.md deleted file mode 100644 index 8fafb47a..00000000 --- a/website/versioned_docs/version-0.104.0/documentation_index.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Documentation -id: version-0.104.0-documentation_index -original_id: documentation_index ---- - -The user documentation is located at [https://www.home-assistant.io](https://www.home-assistant.io). This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. You work on your change and propose it via a Pull Request (PR). - -Once you've created a Pull Request (PR), you can see a preview of the proposed changes by clicking *Details* against Netlify checker in the checkers section of the PR as soon as deployment is complete. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process of working on the website is no different from working on Home Assistant itself. - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.5.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` (You might have to run this command as `sudo`). - -- Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` -- Shortcut for Debian/Ubuntu: `$ sudo apt-get install ruby ruby-dev ruby-bundler ruby-json g++ zlib1g-dev && bundle` - -- Fork the home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.io). -- In your home-assistant.io root directory, run `$ bundle` to install the gems you need. - -Then you can work on the documentation: - -- Run `bundle exec rake generate` to generate the very first preview. This will take a minute. -- Create/edit/update a page. The integration/platforms documentation is located in `source/_integrations/`. `source/_docs/` contains the Home Assistant documentation itself. -- Test your changes to home-assistant.io locally: run `bundle exec rake preview` and navigate to [http://127.0.0.1:4000](http://127.0.0.1:4000). While this command is working, any changes to a file are automatically detected and will update the affected pages. You will have to manually reload them in the browser though. -- Create a Pull Request (PR) against the **next** branch of home-assistant.io if your documentation is a new feature, platform, or integration. -- Create a Pull Request (PR) against the **current** branch of home-assistant.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -The site generated by `bundle exec rake` is only available locally. If you are developing on a headless machine, use port forwarding: - -```shell -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` - -## Speeding up site generation - -Every release we post long changelogs to the website. This slows down generation of the website a bit. We've include some tools to temporarily exclude integrations and blog posts that you're not working on out of the way. - -```shell -bundle exec rake isolate[filename-of-blogpost-or-integration] -``` - -When you're done working on the site, run the following command to move the pages back again: - -```shell -bundle exec rake integrate -``` diff --git a/website/versioned_docs/version-0.104.0/entity_cover.md b/website/versioned_docs/version-0.104.0/entity_cover.md deleted file mode 100644 index da2e7610..00000000 --- a/website/versioned_docs/version-0.104.0/entity_cover.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: Cover Entity -sidebar_label: Cover -id: version-0.104.0-entity_cover -original_id: entity_cover ---- - -A cover entity is a device that controls an opening or cover, such as a garage door and window shade. Derive entity platforms from [`homeassistant.components.cover.CoverDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/cover/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -### Platform Properties (to be implemented by deriving platform classes) - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| current_cover_position | int | None | The current position of cover where 0 means closed and 100 is fully open. Required with `SUPPORT_SET_POSITION`. -| current_cover_tilt_position | int | None | The current tilt position of the cover where 0 means closed/no tilt and 100 means open/maximum tilt. Required with `SUPPORT_SET_TILT_POSITION` -| is_opening | bool | None | If the cover is opening or not. Used to determine `state`. -| is_closing | bool | None | If the cover is closing or not. Used to determine `state`. -| is_closed | bool | `NotImplementedError()` | If the cover is closed or not. if the state is unknown, return `None`. Used to determine `state`. - -### Entity Properties (base class properties which may be overriden) - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| device_class | string | None | Describes the type/class of the cover. Must be `None` or one of the valid values from the table below. -| supported_features | int (bitwise) | Value determined from `current_cover_position` and `current_cover_tilt_position` | Describes the supported features. See the related table below for details. - -### Device Classes -| Constant | Description -|----------|-----------------------| -| `DEVICE_CLASS_AWNING` | Control of an awning, such as an exterior retractible window, door, or patio cover. -| `DEVICE_CLASS_BLIND` | Control of blinds, which are linked slats that expand or collapse to cover an opening or may be tilted to partially cover an opening, such as window blinds. -| `DEVICE_CLASS_CURTAIN` | Control of curtains or drapes, which is often fabric hung above a window or door that can be drawn open. -| `DEVICE_CLASS_DAMPER` | Control of a mechanical damper that reduces air flow, sound, or light. -| `DEVICE_CLASS_DOOR` | Control of a door or gate that provides access to an area. -| `DEVICE_CLASS_GARAGE` | Control of a garage door that provides access to a garage. -| `DEVICE_CLASS_SHADE` | Control of shades, which are a continous plane of material or connected cells that expanded or collapsed over an opening, such as window shades. -| `DEVICE_CLASS_SHUTTER` | Control of shutters, which are linked slats that swing out/in to cover an opening or may be tilted to partially cover an opening, such as indoor or exterior window shutters. -| `DEVICE_CLASS_WINDOW` | Control of a physical window that opens and closes or may tilt. - -### States -| Constant | Description -|----------|------------------------| -| `STATE_OPENING` | The cover is in the process of opening to reach a set position. -| `STATE_OPEN` | The cover has reached the open position. -| `STATE_CLOSING` | The cover is in the process of closing to reach a set position. -| `STATE_CLOSED` | The cover has reach the closed position. - - -### Supported Features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Constant | Description | -|----------|--------------------------------------| -| `SUPPORT_OPEN` | The cover supports being opened. -| `SUPPORT_CLOSE` | The cover supports being closed. -| `SUPPORT_SET_POSITION` | The cover supports moving to a specific position between opened and closed. -| `SUPPORT_STOP` | The cover supports stopping the current action (open, close, set position) -| `SUPPORT_OPEN_TILT` | The cover supports being tilting open. -| `SUPPORT_CLOSE_TILT` | The cover supports being tilting closed. -| `SUPPORT_SET_TILT_POSITION` | The cover supports moving to a specific tilt position between opened and closed. -| `SUPPORT_STOP_TILT` | The cover supports stopping the current tilt action (open, close, set position) - -## Methods - -### Open cover - -Only implement this method if the flag `SUPPORT_OPEN` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover(self, **kwargs): - """Open the cover.""" - - async def async_open_cover(self, **kwargs): - """Open the cover.""" -``` - -### Close cover - -Only implement this method if the flag `SUPPORT_CLOSE` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover(self, **kwargs): - """Close cover.""" - - async def async_close_cover(self, **kwargs): - """Close cover.""" -``` - -### Set cover position - -Only implement this method if the flag `SUPPORT_SET_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" - - async def async_set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" -``` - -### Stop cover - -Only implement this method if the flag `SUPPORT_STOP` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover(self, **kwargs): - """Stop the cover.""" -``` - -### Open cover tilt - -Only implement this method if the flag `SUPPORT_OPEN_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" - - async def async_open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" -``` - -### Close cover tilt - -Only implement this method if the flag `SUPPORT_CLOSE_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" - - async def async_close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" -``` - -### Set cover tilt position - -Only implement this method if the flag `SUPPORT_SET_TILT_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" - - async def async_set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" -``` - -### Stop cover tilt - -Only implement this method if the flag `SUPPORT_STOP_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover_tilt(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover_tilt(self, **kwargs): - """Stop the cover.""" -``` diff --git a/website/versioned_docs/version-0.104.0/entity_fan.md b/website/versioned_docs/version-0.104.0/entity_fan.md deleted file mode 100644 index 8385b24d..00000000 --- a/website/versioned_docs/version-0.104.0/entity_fan.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Fan Entity -sidebar_label: Fan -id: version-0.104.0-entity_fan -original_id: entity_fan ---- - -A fan entity is a device that controls the different vectors of your fan such as speed, direction and oscillation. Derive enitity platforms from ['homeassistant.components.fan.FanDevice'](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/fan/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| current_direction | str | None | Return the current direction of the fan | -|is_on| boolean | None |Return true if the entity is on | -| speed | str | None | Return the current speed | -| speed_list | list | None| Get the list of available speeds | -| state_attributes | dict | None | Return optional state attributes | -| supported_features | int | None | Flag supported features | - - -## Supported Features - -| Constant | Description | -|----------|--------------------------------------| -| 'SUPPORT_DIRECTION' | The fan supports changing the direction of it. -| 'SUPPORT_SET_SPEED' | The fan supports setting the speed. -| 'SUPPORT_OSCILLATE' | The fan supports oscillation. - - - -## Methods - -### Set direction - -Only implement this method if the flag `SUPPORT_DIRECTION` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def set_direction(self, direction: str) -> None: - """Set the direction of the fan.""" - - async def async_set_direction(self, direction: str): - """Set the direction of the fan.""" -``` - -### Set speed - -Only implement this method if the flag `SUPPORT_SET_SPEED` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def set_speed(self, speed: str) -> None: - """Set the speed of the fan.""" - - async def async_set_speed(self, speed: str): - """Set the speed of the fan.""" -``` - -### Turn on - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def turn_on(self, speed: str = None, **kwargs) -> None: - """Turn on the fan.""" - - async def async_turn_on(self, speed: str = None, **kwargs): - """Turn on the fan.""" -``` - -### Oscillate - -Only implement this method if the flag `SUPPORT_OSCILLATE` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def oscillate(self, oscillating: bool) -> None: - """Oscillate the fan.""" - - def async_oscillate(self, oscillating: bool): - """Oscillate the fan.""" -``` - - - - - - diff --git a/website/versioned_docs/version-0.104.0/entity_index.md b/website/versioned_docs/version-0.104.0/entity_index.md deleted file mode 100644 index 4c07065a..00000000 --- a/website/versioned_docs/version-0.104.0/entity_index.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Entity -sidebar_label: Introduction -id: version-0.104.0-entity_index -original_id: entity_index ---- - -Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating. - -Below is an example switch entity that keeps track of their state in memory. - -```python -from homeassistant.components.switch import SwitchDevice - - -class MySwitch(SwitchDevice): - def __init__(self): - self._is_on = False - - @property - def name(self): - """Name of the device.""" - return "My Switch" - - @property - def is_on(self): - """If the switch is currently on or off.""" - return self._is_on - - def turn_on(self, **kwargs): - """Turn the switch on.""" - self._is_on = True - - def turn_off(self, **kwargs): - """Turn the switch off.""" - self._is_on = False -``` - -That's all there is to it to build a switch entity! Continue reading to learn more or check out the [video tutorial](https://youtu.be/Cfasc9EgbMU?t=737). - -## Updating the entity - -An entity represents a device. There are various strategies to keep your entity in sync with the state of the device, the most popular one being polling. - -### Polling - -With polling, Home Assistant will ask the entity from time to time (depending on the update interval of the component) to fetch the latest state. Home Assistant will poll an entity when the `should_poll` property returns `True` (the default value). You can either implement your update logic using `update()` or the async method `async_update()`. This method should fetch the latest state from the device and store it in an instance variable for the properties to return it. - -### Subscribing to updates - -When you subscribe to updates, your code is responsible for letting Home Assistant know that an update is available. Make sure you have the `should_poll` property return `False`. - -Whenever you receive new state from your subscription, you can tell Home Assistant that an update is available by calling `schedule_update_ha_state()` or async callback `async_schedule_update_ha_state()`. Pass in the boolean `True` to the method if you want Home Assistant to call your update method before writing the update to Home Assistant. - -## Generic properties - -The entity base class has a few properties that are common among all entities in Home Assistant. These can be added to any entity regardless of the type. All these properties are optional and don't need to be implemented. - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| assumed_state | boolean | `False` | Return `True` if the state is based on our assumption instead of reading it from the device. -| available | boolean | `True` | Indicate if Home Assistant is able to read the state and control the underlying device. -| device_state_attributes | dict | `None` | Extra information to store in the state machine. It needs to be information that further explains the state, it should not be static information like firmware version. See [below](entity_index.md#standard-attributes) for details of standard attributes. -| entity_picture | URL | `None` | Url of a picture to show for the entity. -| name | string | `None` | Name of the entity -| should_poll | boolean | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](#methods). -| unique_id | string | `None` | A unique identifier for this entity. Needs to be unique within a platform (ie `light.hue`). Should not be configurable by the user or be changeable. [Learn more.](entity_registry_index.md#unique-id-requirements) - -## Advanced properties - -The following properties are also available on entities. However, they are for advanced use only and should be used with caution. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| force_update | boolean | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine. -| hidden | boolean | `False` | Indicate if the entity should not be shown on the frontend. -| icon | icon | `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all devices. -| entity_registry_enabled_default | boolean | `True` | Indicate if the entity should be enabled or disabled when it is first added to the entity registry. - -## System properties - -The following properties are used and controlled by Home Assistant, and should not be overridden by integrations. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| enabled | boolean | `True` | Indicate if entity is enabled in the entity registry. It also returns `True` if the platform doesn't support the entity registry. Disabled entities will not be added to Home Assistant. - -## Standard attributes - -The following `device_state_attributes` are considered standard and should follow the convention below. The constant should be imported from `homeassistant/const.py`. - -| Name | Type | Unit | Constant | Description -| ---- | ---- | ---- | -------- | ----------- -| battery_charging | boolean | N/A | `ATTR_BATTERY_CHARGING` | Battery charging status of the entity, shown as a boolean `true` or `false`. If charging is not supported, then this attribute should not be created. -| battery_level | integer | % | `ATTR_BATTERY_LEVEL` | Battery level of the entity, shown as an integer percentage between 0-100. - -## Lifecycle hooks - -Use these lifecycle hooks to execute code when certain events happen to the entity. All lifecycle hooks are async methods. - -### `async_added_to_hass()` - -Called when an entity has their entity_id and hass object assigned, before it is written to the state machine for the first time. Example uses: restore the state, subscribe to updates or set callback/dispatch function/listener. - -### `async_will_remove_from_hass()` - -Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates. - -## Changing the entity model - -If you want to add a new feature to an entity or any of its subtypes (light, switch, etc), you will need to propose it first in our [architecture repo](https://github.com/home-assistant/architecture/issues). Only additions will be considered that are common features among various vendors. diff --git a/website/versioned_docs/version-0.104.0/entity_light.md b/website/versioned_docs/version-0.104.0/entity_light.md deleted file mode 100644 index 125cacd3..00000000 --- a/website/versioned_docs/version-0.104.0/entity_light.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Light Entity -sidebar_label: Light -id: version-0.104.0-entity_light -original_id: entity_light ---- - - -A light entity is a device that controls the brightness, RGB value,color temperature and effects of a light source. - -## Properties - -| Name | Type | Default | Description -| ---- | ---- | ---- | ---- -| brightness | int | None | Return the brightness of this light between 0..255 -| color_temp | int | None | Return the CT color value in mireds. -| effect | String | None | Return the current effect. -| effect_list | list | None | Return the list of supported effects. -| hs_color | list | None | Return the hue and saturation color value [float, float]. -| is_on | bool | bool | Returns if the light entity is on or not. -| max_minreds | int | int | Return the warmest color_temp that this light supports. -| min_mireds | int | int | Return the coldest color_temp that this light supports. -| supported_features | int | int | Flag supported features. -| white_value | int | None | Return the white value of this light between 0..255. - - -## Support Feature -| Constant | Description -|----------|----------------------- -| `SUPPORT_BRIGHTNESS` | Controls the brightness of a light source -| `SUPPORT_COLOR` | Controls the color a light source shows -| `SUPPORT_COLOR_TEMP` | Controls the representation a light source shows based on temperature -| `SUPPORT_EFFECT` | Controls the effect a light source shows -| `SUPPORT_FLASH` | Controls the duration of a flash a light source shows -| `SUPPORT_TRANSITION` | Controls the duration of transitions between color and effects -| `SUPPORT_WHITE_VALUE` | Controls the white light a light source shows. - -## Methods - -# Turn on Light Device - -```python -class MyLightDevice(LightDevice): - def turn_on(self, **kwargs): - """Turn the device on.""" - - async def async_turn_on(self, **kwargs): - """Turn device on.""" -``` - -# Turn Off Light Device - -```python -class MyLightDevice(LightDevice): - def turn_off(self, **kwargs): - """Turn the device off.""" - - async def async_turn_off(self, **kwargs): - """Turn device off.""" -``` diff --git a/website/versioned_docs/version-0.104.0/entity_media_player.md b/website/versioned_docs/version-0.104.0/entity_media_player.md deleted file mode 100644 index 806d058b..00000000 --- a/website/versioned_docs/version-0.104.0/entity_media_player.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Media Player Entity -sidebar_label: Media Player -id: version-0.104.0-entity_media_player -original_id: entity_media_player ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| sound_mode | string | None | The current sound mode of the media player -| sound_mode_list | list | None | Dynamic list of available sound modes (set by platform, empty means sound mode not supported) -| source | string | None | The currently selected input source for the media player. -| source_list | list | None | The list of possible input sources for the media player. (This list should contain human readable names, suitible for frontend display) -| media_image_url | string | None | URL that represents the current image. -| media_image_remotely_accessible | boolean | False | Return `True` if property `media_image_url` is accessible outside of the home network. -| device_class | string | `None` | Type of media player. - -## Methods -### Select sound mode -Optional. Switch the sound mode of the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - def async_select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - -### Select source -Optional. Switch the selected input source for the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_source(self, source): - """Select input source.""" - - def async_select_source(self, source): - """Select input source.""" - -### Mediatype -Required. Returns one of the defined constants from the below list that matches the mediatype - -| CONST | -|-------| -|MEDIA_TYPE_MUSIC| -|MEDIA_TYPE_TVSHOW| -|MEDIA_TYPE_MOVIE| -|MEDIA_TYPE_VIDEO| -|MEDIA_TYPE_EPISODE| -|MEDIA_TYPE_CHANNEL| -|MEDIA_TYPE_PLAYLIST| -|MEDIA_TYPE_IMAGE| -|MEDIA_TYPE_URL| -|MEDIA_TYPE_GAME| -|MEDIA_TYPE_APP| - - class MyMediaPlayer(MediaPlayerDevice): - # Implement the following method. - - def media_content_type(self): - """Content type of current playing media.""" - -### Available device classes -Optional. What type of media device is this. It will possibly map to google device types. -| Value | Description -| ----- | ----------- -| tv | Device is a television type device. -| speaker | Device is speakers or stereo type device. diff --git a/website/versioned_docs/version-0.104.0/entity_switch.md b/website/versioned_docs/version-0.104.0/entity_switch.md deleted file mode 100644 index c8f95b2d..00000000 --- a/website/versioned_docs/version-0.104.0/entity_switch.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: Switch Entity -sidebar_label: Switch -id: version-0.104.0-entity_switch -original_id: entity_switch ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| is_on | boolean | **Required** | If the switch is currently on or off. -| current_power_w | float | `None` | The current power usage in W. -| today_energy_kwh | float | `None` | Total energy usage in kWh. -| is_standby | boolean | `None` | Indicate if the device connected to the switch is currently in standby. - -## Methods - -### Turn On - -Turn the switch on. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def turn_on(self, **kwargs) -> None: - """Turn the entity on.""" - - async def async_turn_on(self, **kwargs): - """Turn the entity on.""" -``` - -### Turn Off - -Turn the switch off. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def turn_off(self, **kwargs): - """Turn the entity off.""" - - async def async_turn_off(self, **kwargs): - """Turn the entity off.""" -``` - -### Toggle - -Optional. If not implemented will default to checking what method to call using the `is_on` property. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def toggle(self, **kwargs): - """Toggle the entity.""" - - async def async_toggle(self, **kwargs): - """Toggle the entity.""" -``` - -### Available device classes -Optional. What type of device this. It will possibly map to google device types. -| Value | Description -| ----- | ----------- -| outlet | Device is an outlet for power. -| switch | Device is switch for some type of entity. diff --git a/website/versioned_docs/version-0.104.0/external_api_rest.md b/website/versioned_docs/version-0.104.0/external_api_rest.md deleted file mode 100644 index 7d45c638..00000000 --- a/website/versioned_docs/version-0.104.0/external_api_rest.md +++ /dev/null @@ -1,552 +0,0 @@ ---- -title: REST API -id: version-0.104.0-external_api_rest -original_id: external_api_rest ---- - -Home Assistant provides a RESTful API on the same port as the web frontend. (default port is port 8123). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -* http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -* http://IP_ADDRESS:8123/api/ is a RESTful API. - -The API accepts and returns only JSON encoded objects. - -All API calls have to be accompanied by the header `Authorization: Bearer ABCDEFGH`, where `ABCDEFGH` is replaced by your token. You can obtain a token ("Long-Lived Access Token") by logging into the frontend using a web browser, and going to [your profile](https://www.home-assistant.io/docs/authentication/#your-account-profile) `http://IP_ADDRESS:8123/profile`. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```shell -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. - -```python -from requests import get - -url = "http://localhost:8123/ENDPOINT" -headers = { - "Authorization": "Bearer ABCDEFGH", - "content-type": "application/json", -} - -response = get(url, headers=headers) -print(response.text) -``` -Another option is to use the Restful Command component https://www.home-assistant.io/components/rest_command/ in a Home Assistant automation or script. - -```yaml -turn_light_on: - url: http://localhost:8123/api/states/light.study_light - method: POST - headers: - authorization: 'Bearer ABCDEFGH' - content-type: 'application/json' - payload: '{"state":"on"}' -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on one or more entities - comma separated. -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates a state. You can create any state that you want, it does not have to be backed by an entity in Home Assistant. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```shell -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```shell -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```shell -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```shell -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now() }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/config/core/check_config - -Trigger a check of `configuration.yaml`. No additional data needs to be passed in with this request. - -If the check is successful, the following will be returned: - -```javascript -{ - "errors": null, - "result": "valid" -} -``` - -If the check fails, the errors attribute in the object will list what caused the check to fail. For example: - -```javascript -{ - "errors": "Integration not found: frontend:", - "result": "invalid" -} -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance.
- -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` diff --git a/website/versioned_docs/version-0.104.0/external_api_server_sent_events.md b/website/versioned_docs/version-0.104.0/external_api_server_sent_events.md deleted file mode 100644 index 2b4947ad..00000000 --- a/website/versioned_docs/version-0.104.0/external_api_server_sent_events.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Server-sent events -id: version-0.104.0-external_api_server_sent_events -original_id: external_api_server_sent_events ---- - -The [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) feature is a one-way channel from your Home Assistant server to a client which is acting as a consumer. For a bi-directional streaming API, check out the [WebSocket API](external_api_websocket.md). - -The URI that is generating the data is `/api/stream`. - -A requirement on the client-side is existing support for the [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) interface. - -There are various ways to access the stream. If you have not set an `api_password` in the [`http`](https://www.home-assistant.io/components/http/) section of your `configuration.yaml` file then you use your modern browser to read the messages. A command-line option is `curl`: - -```shell -$ curl -X GET -H 'Authorization: Bearer ABCDEFGH' \ - -H "Content-Type: application/json" http://localhost:8123/api/stream -``` - -> Will no longer work with the new Authentication system. - -You can create a convenient view for this by creating an HTML file (`sse.html`) in the `www` folder of your Home Assistant configuration directory (`.homeassistant`). Paste this snippet into the file: - -```html - - - -

Getting Home Assistant server events

-
- - - -``` - -Visit [http://localhost:8123/local/sse.html](http://localhost:8123/local/sse.html) to see the stream of events. - -## Examples - -A simple way to consume server-sent events is to use a command-line http client like [httpie](https://httpie.org/). Installation info is on the site (if you use Homebrew, it's `brew install httpie`). Once installed, run this snippet from your terminal: - -```shell -$ http --stream http://localhost:8123/api/stream 'Authorization:Bearer ABCDEFGH' content-type:application/json -``` - -### Website - -> Will no longer work with the new Authentication system. - -The [home-assistant-sse](https://github.com/fabaff/home-assistant-sse) repository contains a more advanced example. - -### Python - -If you want to test the server-sent events without creating a website, the Python module [`sseclient` ](https://pypi.python.org/pypi/sseclient/) can help. To install (assuming Python and pip3 are already installed): - -```shell -$ pip3 install sseclient -``` - -A simple script to consume SSE in Python looks like this: - -```python -from sseclient import SSEClient - -auth = {"Authorization": "Bearer ABCDEFGH"} -messages = SSEClient("http://localhost:8123/api/stream", headers=auth) - -for msg in messages: - print(msg) -``` diff --git a/website/versioned_docs/version-0.104.0/frontend_add_websocket_api.md b/website/versioned_docs/version-0.104.0/frontend_add_websocket_api.md deleted file mode 100644 index f7591bf1..00000000 --- a/website/versioned_docs/version-0.104.0/frontend_add_websocket_api.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: Extending the WebSocket API -id: version-0.104.0-frontend_add_websocket_api -original_id: frontend_add_websocket_api ---- - -As a component you might have information that you want to make available to the frontend. For example, the media player will want to make album covers available for the frontend to show. Our frontend is communicating with the backend over the websocket API, which can be extended with custom commands. - -## Registering a command (Python) - -To register a command, you need to have a message type, a message schema and a message handler. Your component does not have to add the websocket API as a dependency. You register your command, and if the user is using the websocket API, the command will be made available. - -### Message Types - -Message types are made up the domain and the message type, separated by a forward slash. In the below example, we're defining `media_player/thumbnail`. - -```python -# The type of the message -WS_TYPE_MEDIA_PLAYER_THUMBNAIL = "media_player/thumbnail" -``` - -### Message Schema - -The message schema defines what type of data we expect when the message is invoked. It is defined as a voluptuous schema and has to extend the base web socket command schema. - -```python -import voluptuous as vol - -from homeassistant.components import websocket_api -import homeassistant.helpers.config_validation as cv - - -# The schema for the message -SCHEMA_WEBSOCKET_GET_THUMBNAIL = websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend( - { - "type": WS_TYPE_MEDIA_PLAYER_THUMBNAIL, - # The entity that we want to retrieve the thumbnail for. - "entity_id": cv.entity_id, - } -) -``` - -### Defining a handler - -Message handlers are callback functions that are run inside the event loop. If you want to do I/O or have to wait for your result, create a new function and queue it up using `hass.async_add_job`. This is done so that the websocket API can get back to handling the next message as soon as possible. - -#### Sending a direct response - -If you are defining a command that is querying simple information, you might be able to fulfill the request while the handler is being called by the websocket API. To do this, use `connection.to_write.put_nowait`. - -```python -@callback -def websocket_handle_thumbnail(hass, connection, msg): - """Handle getting a thumbnail.""" - - # We know the answer without having to fetch any information, - # so we send it directly. - connection.to_write.put_nowait( - websocket_api.result_message( - msg["id"], {"thumbnail": "http://via.placeholder.com/350x150"} - ) - ) -``` - -#### Sending a delayed response - -If your command needs to interact with the network, a device or needs to compute information, you will need to queue a job to do the work and send the response. To do this, use `connection.send_message_outside`. - -```python -@callback -def websocket_handle_thumbnail(hass, connection, msg): - """Handle get media player cover command.""" - # Retrieve media player using passed in entity id. - player = hass.data[DOMAIN].get_entity(msg["entity_id"]) - - # If the player does not exist, send an error message. - if player is None: - connection.to_write.put_nowait( - websocket_api.error_message( - msg["id"], "entity_not_found", "Entity not found" - ) - ) - return - - # Define a function to be enqueued. - async def send_image(): - """Send image.""" - data, content_type = await player.async_get_media_image() - - # No media player thumbnail available - if data is None: - connection.send_message_outside( - websocket_api.error_message( - msg["id"], "thumbnail_fetch_failed", "Failed to fetch thumbnail" - ) - ) - return - - connection.send_message_outside( - websocket_api.result_message( - msg["id"], - { - "content_type": content_type, - "content": base64.b64encode(data).decode("utf-8"), - }, - ) - ) - - # Player exist. Queue up a job to send the thumbnail. - hass.async_add_job(send_image()) -``` - -### Registering with the Websocket API - -With all pieces defined, it's time to register the command. This is done inside your setup method. - -```python -async def async_setup(hass, config): - """Setup of your component.""" - hass.components.websocket_api.async_register_command( - WS_TYPE_MEDIA_PLAYER_THUMBNAIL, - websocket_handle_thumbnail, - SCHEMA_WEBSOCKET_GET_THUMBNAIL, - ) -``` - -## Calling the command from the frontend (JavaScript) - -With your command defined, it's time to call it from the frontend! This is done using JavaScript. You will need access to the `hass` object which holds the WebSocket connection to the backend. Then just call `hass.connection.sendMessagePromise`. This will return a promise that will resolve if the command succeeds and errors if the command fails. - -```js -hass.connection.sendMessagePromise({ - type: 'media_player/thumbnail', - entity_id: 'media_player.living_room_tv', -}).then( - (resp) => { - console.log('Message success!', resp.result); - }, - (err) => { - console.error('Message failed!', err); - } -); -``` - -If your command is not sending a response, you can use `hass.connection.sendMessage`. diff --git a/website/versioned_docs/version-0.104.0/frontend_creating_custom_ui.md b/website/versioned_docs/version-0.104.0/frontend_creating_custom_ui.md deleted file mode 100644 index d11ca230..00000000 --- a/website/versioned_docs/version-0.104.0/frontend_creating_custom_ui.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Creating custom UI -id: version-0.104.0-frontend_creating_custom_ui -original_id: frontend_creating_custom_ui ---- - -> This feature has been deprecated and is no longer supported. To add custom UI to Home Assistant, build a [custom Lovelace card](lovelace_custom_card.md) instead. - -### State card - -If you would like to use your own [State card](frontend_add_card.md) without merging your code into [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer/) you can create your own implementation. - -Put the element source file and its dependencies in `www/custom_ui/` directory under your Home Assistant [configuration](https://www.home-assistant.io/docs/configuration/) directory. - -For example if creating a state card for the `light` domain named `state-card-my-custom-light` put `state-card-my-custom-light.html` in `www/custom_ui/`. - -That file should implement `` tag with Polymer. - -In `state-card-my-custom-light.html` you should use `` to import all the dependencies **not** used by Home Assistant's UI. -Do not import any dependencies used by the Home Assistant UI. -Importing those will work in `development: 1` mode, but will fail in production mode. - -1. In the `customize:` section of the `configuration.yaml` file put `custom_ui_state_card: state-card-my-custom-light`. -2. In the `frontend` section use `extra_html_url` to specify the URL to load. - -Example: - -`configuration.yaml`: - -```yaml -homeassistant: - customize: - light.bedroom: - custom_ui_state_card: state-card-my-custom-light - -frontend: - extra_html_url: - - /local/custom_ui/state-card-my-custom-light.html -``` - -`www/custom_ui/state-card-my-custom-light.html`: - -```html - - - - - - -``` - -> Some browsers don't support latest ECMAScript standards, these require a separate ES5 compatible file (`extra_html_url_es5`). - -For more possibilities, see the [Custom UI section](https://www.home-assistant.io/cookbook/#user-interface) on our Examples page. - -### More info dialog - -_Introduced in Home Assistant 0.69._ - -Similar to the custom State card, if you would like to use your own [More info dialog](frontend_add_more_info.md) you can create your own implementation. - -Following a similar example, if creating a more info dialog a light named `more-info-my-custom-light` put `more-info-my-custom-light.html` in `www/custom_ui/`. - -1. In the `customize:` section of the `configuration.yaml` file put `custom_ui_more_info: more-info-my-custom-light`. -2. In the `frontend` section use `extra_html_url` to specify the URL to load. - -Example: - -`configuration.yaml`: - -```yaml -homeassistant: - customize: - light.bedroom: - custom_ui_more_info: more-info-my-custom-light - -frontend: - extra_html_url: - - /local/custom_ui/more-info-my-custom-light.html -``` diff --git a/website/versioned_docs/version-0.104.0/frontend_development.md b/website/versioned_docs/version-0.104.0/frontend_development.md deleted file mode 100644 index 99c8e28e..00000000 --- a/website/versioned_docs/version-0.104.0/frontend_development.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Frontend development -sidebar_label: Development -id: version-0.104.0-frontend_development -original_id: frontend_development ---- - -The Home Assistant frontend is built using web components. For more background about our technology choices, [see this blog post](https://developers.home-assistant.io/blog/2019/05/22/internet-of-things-and-the-modern-web.html). - -> Do not use development mode in production. Home Assistant uses aggressive caching to improve the mobile experience. This is disabled during development so that you do not have to restart the server in between changes. - -## Setting up the environment - -### Getting the code - -First step is to fork the [home-assistant-polymer repository][hass-polymer] and add the upstream remote. You can place the forked repository anywhere on your system. - -```shell -$ git clone git@github.com:YOUR_GIT_USERNAME/home-assistant-polymer.git -$ cd home-assistant-polymer -$ git remote add upstream https://github.com/home-assistant/home-assistant-polymer.git -``` - -### Configuring Home Assistant - -You will need to have an instance of Home Assistant set up. See our guide on [setting up a development environment](https://developers.home-assistant.io/docs/en/development_environment.html). - -Next step is to configure Home Assistant to use the development mode for the frontend. Do this by updating the frontend config in your `configuration.yaml` and set the path to the home-assistant-polymer repository that you cloned in the last step: - -```yaml -frontend: - # Example absolute path: /home/paulus/dev/hass/home-assistant-polymer - development_repo: -``` - -### Installing Node.js - -Node.js is required to build the frontend. The preferred method of installing node.js is with [nvm](https://github.com/creationix/nvm). Install nvm using the instructions in the [README](https://github.com/creationix/nvm#install-script), and install the correct node.js by running the following command: - -```shell -$ nvm install -``` - -[Yarn](https://yarnpkg.com/en/) is used as the package manager for node modules. [Install yarn using the instructions here.](https://yarnpkg.com/en/docs/install) - -Next, development dependencies need to be installed to bootstrap the frontend development environment. First activate the right Node version and then download all the dependencies: - -```shell -$ nvm use -$ script/bootstrap -``` - -## Development - -During development, you will need to run the development script to maintain a development build of the frontend that auto updates when you change any of the source files. To run this server, run: - -```shell -$ nvm use -$ script/develop -``` - -Make sure you have cache disabled and correct settings to avoid stale content: - -> Instructions are for Google Chrome - -1. Disable cache by ticking the box in `Network` > `Disable cache` - -

- -

- -2. Enable Bypass for network in `Application` > `Service Workers` > `Bypass for network` - -

- -

- -## Creating pull requests - -If you're planning on issuing a PR back to the Home Assistant codebase you need to fork the polymer project and add your fork as a remote to the Home Assistant Polymer repo. - -```shell -$ git remote add fork -``` - -When you've made your changes and are ready to push them change to the working directory for the polymer project and then push your changes - -``` bash -$ git add -A -$ git commit -m "Added new feature X" -$ git push -u fork HEAD -``` - -## Building the Polymer frontend - -If you're making changes to the way the frontend is packaged, it might be necessary to try out a new packaged build of the frontend in the main repository (instead of pointing it at the frontend repo). To do so, first build a production version of the frontend by running `script/build_frontend`. - -To test it out inside Home Assistant, run the following command from the main Home Assistant repository: - -```shell -$ pip3 install -e /path/to/home-assistant-polymer/ -$ hass --skip-pip -``` - -[hass-polymer]: https://github.com/home-assistant/home-assistant-polymer diff --git a/website/versioned_docs/version-0.104.0/frontend_external_auth.md b/website/versioned_docs/version-0.104.0/frontend_external_auth.md deleted file mode 100644 index 78e1fe2d..00000000 --- a/website/versioned_docs/version-0.104.0/frontend_external_auth.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: External Authentication -id: version-0.104.0-frontend_external_auth -original_id: frontend_external_auth ---- - -By default, the frontend will take care of its own authentication tokens. If none found, it will redirect the user to the login page and it will take care that the token is up to date. - -If you want to embed the Home Assistant frontend in an external app, you will want to store the authentication inside the app but make it available to the frontend. To support this, Home Assistant exposes an external authentication API. - -To activate this API, load the frontend with `?external_auth=1` appended to the URL. If this is passed in, Home Assistant will expect either `window.externalApp` (for Android) or `window.webkit.messageHandlers` (for iOS) to be defined containing the methods described below. - -## Get Access Token - -_This API has been introduced in Home Assistant 0.78._ - -When the frontend loads, it will request an access token from the external authentication. It does so by calling one of the following methods with an options object. The options object defines the callback method to be called with the response and an optional `force` boolean which is set to `true` if the access token should be refreshed, regardless if it has expired or not. - -The `force` boolean has been introduced in Home Assistant 0.104 and might not always be available. - -```js -window.externalApp.getExternalAuth({ - callback: "externalAuthSetToken", - force: true -}); -// or -window.webkit.messageHandlers.getExternalAuth.postMessage({ - callback: "externalAuthSetToken", - force: true -}); -``` - -The response should contain a boolean if it was successful and an object containing an access token and the number of seconds that it will remain valid. Pass the response to the function defined in the options object. - -```js -// To be called by external app -window.externalAuthSetToken(true, { - access_token: "qwere", - expires_in: 1800 -}); - -// If unable to get new access token -window.externalAuthSetToken(false); -``` - -The frontend will call this method when the page first loads and whenever it needs a valid token but the previous received token has expired. - -## Revoke Token - -_This API has been introduced in Home Assistant 0.78._ - -When the user presses the logout button on the profile page, the external app will have to [revoke the refresh token](auth_api.md#revoking-a-refresh-token), and log the user out. - -```js -window.externalApp.revokeExternalAuth({ - callback: "externalAuthRevokeToken" -}); -// or -window.webkit.messageHandlers.revokeExternalAuth.postMessage({ - callback: "externalAuthRevokeToken" -}); -``` - -When done, the external app has to call the function defined in the options object. - -```js -// To be called by external app -window.externalAuthRevokeToken(true); - -// If unable to logout -window.externalAuthRevokeToken(false); -``` diff --git a/website/versioned_docs/version-0.104.0/hassio_addon_config.md b/website/versioned_docs/version-0.104.0/hassio_addon_config.md deleted file mode 100644 index d0b827a9..00000000 --- a/website/versioned_docs/version-0.104.0/hassio_addon_config.md +++ /dev/null @@ -1,232 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.104.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - apparmor.txt - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -All our Images have also [bashio][bashio] installed. It contains a set of commonly used operations and can be used to be included in add-ons to reduce code duplication across add-ons and therefore making it easier to develop and maintain add-ons. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use bashio or `jq` inside your shell script to parse this data. - -```shell -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -[bashio]: https://github.com/hassio-addons/bashio - -## Add-on Docker file - -All add-ons are based on latest Alpine Linux. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -```dockerfile -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | yes | List of supported arch: `armhf`, `armv7`, `aarch64`, `amd64`, `i386`. -| machine | list | no | Default it support any machine type. You can select that this add-on run only on specific machines. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | string | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. If host-port is `null`, the mapping is disabled. -| ports_description | dict | no | Network ports description mapping. Format is `"container-port/type": "description of this port"`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| udev | bool | no | Default False. Set this True, if your container run a own udev process. -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| homeassistant | string | no | Pin a minimum required Home Assistant version for such Add-on. Value is a version string like `0.91.2`. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| kernel_modules | bool | no | Map host kernel modules and config into add-on (readonly). -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| auth_api | bool | no | Allow access to Home Assistent user backend. -| ingress | bool | no | Enable the ingress feature for the Add-on -| ingress_port | integer | no | Default `8099`. For Add-ons they run on host network, you can use `0` and read the port later on API. -| ingress_entry | string | no | Modify the URL entry point from `/`. -| panel_icon | string | no | Default: mdi:puzzle. MDI icon for the menu panel integration. -| panel_title | string | no | Default add-on name, but can Modify with this options. -| panel_admin | bool | no | Default True. Make menu entry only available with admin privileged. -| snapshot_exlude | list | no | List of file/path with glob support they are excluded from snapshots. - - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str / str(min,) / str(,max) / str(min,max) -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) -- list(val1|val2|...) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. - -We provide a set of [Base-Images][hassio-base] which should cover a lot of needs. If you don't want use the Alpine based version or need a specific Image tag, feel free to pin this requirements for you build with `build_from` option. - -[hassio-base]: https://github.com/home-assistant/hassio-base diff --git a/website/versioned_docs/version-0.104.0/hassio_addon_publishing.md b/website/versioned_docs/version-0.104.0/hassio_addon_publishing.md deleted file mode 100644 index b0b5bf34..00000000 --- a/website/versioned_docs/version-0.104.0/hassio_addon_publishing.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Publishing your add-on -id: version-0.104.0-hassio_addon_publishing -original_id: hassio_addon_publishing ---- - -There are two different ways of publishing add-ons. One is to publish pre-build containers to Docker Hub and the other option is to have users build the containers locally on their Hass.io instance. - -#### Pre-build containers - -With pre-build containers, the developer is responsible for building the images for each architecture on their machine and push the results out to Docker Hub. This has a lot of advantages for the user. As a user it will only have to download the final container and be up and running once the download finishes. This makes the installation process fast and almost no chance of failure. This is the preferred method. - -We have automated the process of building and publishing add-ons. See below for the instructions. - -#### Locally build containers - -Starting Hass.io 0.26, it is possible to distribute add-ons that will be built on the users machine. The advantage is that as a developer it is easy to test an idea and see if people are interested in your add-ons. This method includes installing and potentially compiling code. This means that installing such an add-on is slow and adds more wear and tear to users SD card/hard drive than the above mentioned pre-build solution. It also has a higher chance of failure if one of the dependencies of the container has changed or is no longer available. - -Use this option when you are playing with add-ons and seeing if someone is interested in your work. Once you're an established repository, please migrate to pushing builds to Docker Hub as it greatly improves the user experience. In the future we will mark locally built add-ons in the add-on store to warn users. - -## Build scripts to publish add-ons to Docker Hub - -All add-ons are simple docker containers. Inside your add-on `config.json` you specify the Docker image that will be installed for your add-on: - -```json -{ - ... - "image": "myhub/image-{arch}-addon-name", - ... -} -``` - -You can use `{arch}` inside the image name to support multiple architectures with one (1) configuration file. It will be replaced with the architecture of the user when we load the image. If you use `Buildargs` you can use the `build.json` to overwrite our default args. - -Hass.io assumes that the `master` branch of your add-on repository matches the latest tag on Docker Hub. When you're building a new version, it's suggested that you use another branch, ie `build` or do it with a PR on GitHub. After you push the add-on to [Docker Hub](https://hub.docker.com/), you can merge this branch to master. - -## Custom Add-ons - -You need a Docker Hub account to make your own add-ons. You can build your Docker images with the Docker `build` command or use our script that make it simple. Pull our [Builder Docker engine][builder] and run one of the following commands. - -For a git repository: - -```shell -$ docker run --rm --privileged -v \ - ~/.docker:/root/.docker homeassistant/amd64-builder \ - --all -t addon-folder -r https://github.com/xy/addons \ - -b branchname -``` - -For a local repository: - -```shell -$ docker run --rm --privileged -v \ - ~/.docker:/root/.docker -v /my_addon:/data homeassistant/amd64-builder \ - --all -t /data -``` - -> If you are developing on macOS and using Docker for Mac, you may encounter an error message similar to the following: error creating aufs mount to /var/lib/docker/aufs/mnt/-init: invalid argument. A proposed workaround is to add the following to the Advanced Daemon JSON configuration via Docker > Preferences > Daemon > Advanced: "storage-driver" : "aufs" or map the docker socket into container. - -[builder]: https://github.com/home-assistant/hassio-builder diff --git a/website/versioned_docs/version-0.104.0/hassio_addon_tutorial.md b/website/versioned_docs/version-0.104.0/hassio_addon_tutorial.md deleted file mode 100644 index d0528df2..00000000 --- a/website/versioned_docs/version-0.104.0/hassio_addon_tutorial.md +++ /dev/null @@ -1,182 +0,0 @@ ---- -title: Tutorial: Making your first add-on -id: version-0.104.0-hassio_addon_tutorial -original_id: hassio_addon_tutorial ---- - -So you've got Home Assistant going and you've been enjoying the built-in add-ons but you're missing this one application. Time to make your own add-on! In Hass.io 0.24 we introduced the option to have local add-ons be build on your device. This is great for developing new add-ons locally. - -To get started with developing add-ons, we first need access to where Hass.io looks for local add-ons. For this you can use the Samba add-on or the SSH add-on. - -For Samba, once you have enabled and started it, your Hass.io instance will show up in your local network tab and share a folder called "addons". This is the folder to store your custom add-ons. - -If you are on macOS and the folder is not showing up automatically, go to Finder and press CMD+K then enter 'smb://hassio.local' - -![Screenshot of Windows Explorer showing a folder on the Hass.io server](/img/en/hass.io/tutorial/samba.png) - -For SSH, you will have to install it. Before you can start it, you will have to have a private/public key pair and store your public key in the add-on config ([see docs for more info][ssh]). Once started, you can SSH to Hass.io and store your custom add-ons in "/addons". - -![Screenshot of Putty connected to Hass.io](/img/en/hass.io/tutorial/ssh.png) - -Once you have located your add-on directory, it's time to get started! - -[ssh]: https://www.home-assistant.io/addons/ssh/ - -## Step 1: The basics - - - Create a new directory called `hello_world` - - Inside that directory create three files. - -`Dockerfile`: -```dockerfile -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -`config.json`: -```json -{ - "name": "Hello world", - "version": "1", - "slug": "hello_world", - "description": "My first real add-on!", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {} -} -``` - -`run.sh`: -```shell -echo Hello world! -``` -Make sure your editor is using UNIX-like line breaks (LF), not Dos/Windows (CRLF). - -## Step 2: Installing and testing your add-on - -Now comes the fun part, time to open the Hass.io UI and install and run your add-on. - - - Open the Home Assistant frontend - - Go to the Hass.io panel - - On the top right click the shopping basket to go to the add-on store. - -![Screenshot of the Hass.io main panel](/img/en/hass.io/screenshots/main_panel_addon_store.png) - - - On the top right click the refresh button - - You should now see a new card called "Local" that lists your add-on! - -![Screenshot of the local repository card](/img/en/hass.io/screenshots/local_repository.png) - - - Click on your add-on to go to the add-on details page. - - Install your add-on - - Start your add-on - - Refresh the logs of your add-on, you should now see "Hello world!" in your logs. - -![Screenshot of the add-on logs](/img/en/hass.io/tutorial/addon_hello_world_logs.png) - -### I don't see my add-on?! - -Oops! You clicked refresh in the store and your add-on didn't show up. Or maybe you just updated an option, clicked refresh and saw your add-on disappear. - -When this happens, it means that your `config.json` is invalid. It's either invalid JSON or one of the specified options is incorrect. To see what went wrong, go to the Hass.io panel and in the supervisor card click on "View logs". This should bring you to a page with the logs of the supervisor. Scroll to the bottom and you should be able to find the validation error. - -Once you fixed the error, go to the add-on store and click refresh again. - -## Step 3: Hosting a server - -Until now we've been able to do some basic stuff, but it's not very useful yet. So let's take it one step further and host a server that we expose on a port. For this we're going to use the built-in HTTP server that comes with Python 3. - -To do this, we will need to update our files as follows: - - - `Dockerfile`: Install Python 3 - - `config.json`: Make the port from the container available on the host - - `run.sh`: Run the Python 3 command to start the HTTP server - -Add to your `Dockerfile` before `RUN`: - -```dockerfile -# Install requirements for add-on -RUN apk add --no-cache python3 - -# Python 3 HTTP Server serves the current working dir -# So let's set it to our add-on persistent data directory. -WORKDIR /data -``` - -Add "ports" to `config.json`. This will make TCP on port 8000 inside the container available on the host on port 8000. - -```json -{ - "name": "Hello world", - "version": "0.2", - "slug": "hello_world", - "description": "My first real add-on!", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {}, - "ports": { - "8000/tcp": 8000 - } -} -``` - -Update `run.sh` to start the Python 3 server: - -```shell -python3 -m http.server 8000 -``` - -## Step 4: Installing the update - -Since we updated the version number in our `config.json`, Home Assistant will show an update button when looking at the add-on details. You might have to refresh your browser or click the refresh button in the add-on store for it to show up. If you did not update the version number, you can also uninstall and install the add-on again. After installing the add-on again, make sure you start it. - -Now navigate to [http://hassio.local:8000](http://hassio.local:8000) to see our server in action! - -![Screenshot of the file index served by the add-on](/img/en/hass.io/tutorial/python3-http-server.png) - -## Bonus: Working with add-on options - -In the screenshot you've probably seen that our server only served up 1 file: `options.json`. This file contains the user configuration for this add-on. Because we specified an empty "config" and "schema" in our `config.json`, the file is currently empty. - -Let's see if we can get some data into that file! - -To do this, we need to specify the default options and a schema for the user to change the options. - -Change the options and schema entries in your `config.json` with the following: - -```json -{ - … - - "options": { - "beer": true, - "wine": true, - "liquor": false, - "name": "world", - "year": 2017 - }, - "schema": { - "beer": "bool", - "wine": "bool", - "liquor": "bool", - "name": "str", - "year": "int" - }, - - … -} -``` - -Refresh the add-on store and re-install your add-on. You will now see the options available in the add-on config screen. When you now go back to our Python 3 server and download `options.json`, you'll see the options you set. [Example of how options.json can be used inside `run.sh`](https://github.com/home-assistant/hassio-addons/blob/master/mosquitto/data/run.sh#L4-L5) diff --git a/website/versioned_docs/version-0.104.0/hassio_debugging.md b/website/versioned_docs/version-0.104.0/hassio_debugging.md deleted file mode 100644 index c9cc6c0b..00000000 --- a/website/versioned_docs/version-0.104.0/hassio_debugging.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Debugging Hass.io -id: version-0.104.0-hassio_debugging -original_id: hassio_debugging ---- - -> This section is not for end users. End users should use the [SSH add-on] to SSH into Hass.io. This is for developers of Hass.io. Do not ask for support if you are using these options. - -[SSH add-on]: https://www.home-assistant.io/addons/ssh/ - -The following debug tips and tricks are for developers who are running the Hass.io image and are working on the base image. If you use the generic Linux installer script, you should be able to access your host and logs as per your host. - -## Debug Supervisor - -Visual Studio Code config: -```json -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Hass.io remote debug", - "type": "python", - "request": "attach", - "port": 33333, - "host": "IP", - "pathMappings": [ - { - "localRoot": "${workspaceFolder}", - "remoteRoot": "/usr/src/hassio" - } - ] - } - ] -} -``` - -You need set the dev mode on supervisor and enable debug with options. You need also install the Remote debug Add-on from Developer Repository to expose the debug port to Host. - -## SSH access to the host -> SSH access through the [SSH add-on] (which will give you SSH access through port 22) will not provide you with all the necessary privileges, and you will be asked for a username and password when typing the 'login' command. You need to follow the steps below, which will setup a separate SSH access through port 22222 with all necessary privileges. - -### resinOS based Hass.io (deprecated) -Create an `authorized_keys` file containing your public key, and place it in the root of the boot partition of your SD card. See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. Once the device is booted, you can access your device as root over SSH on port 22222. - -### HassOS based Hass.io -Use a USB drive formatted with FAT, ext4, or NTFS and name it CONFIG (case sensitive). Create an `authorized_keys` file (no extension) containing your public key, and place it in the root of the USB drive. File needs to be ANSI encoded (not UTF-8) and must have Unix line ends (LF), not Windows (CR LF). See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. From the UI, navigate to the hass.io system page and choose "Import from USB". You can now access your device as root over SSH on port 22222. Alternatively, the file will be imported from the USB when the hass.io device is rebooted. - -> Make sure when you are copying the public key to the root of the USB drive that you rename the file correctly to `authorized_keys` with no `.pub` file extension. - -You should then be able to SSH into your Hass.io device. On Mac/Linux, use: - -```shell -ssh root@hassio.local -p 22222 -``` - -You will initially be logged in to Hass.io CLI for HassOS where you can perform normal [CLI functions]. If you need access to the host system use the 'login' command. [Hass.io OS] is a hypervisor for Docker. See the [Hass.io Architecture] documentation for information regarding the Hass.io supervisor. The supervisor offers an API to manage the host and running the Docker containers. Home Assistant itself and all installed addon's run in separate Docker containers. - -[CLI functions]: https://www.home-assistant.io/hassio/commandline/ -[Hass.io OS]: https://github.com/home-assistant/hassos -[Hass.io Architecture]: https://developers.home-assistant.io/docs/en/architecture_hassio.html - -## Checking the logs - -```shell -# Logs from the supervisor service on the Host OS -journalctl -f -u hassos-supervisor.service - -# Hass.io supervisor logs -docker logs hassos_supervisor - -# Home Assistant logs -docker logs homeassistant -``` - -## Accessing the container bash - -```shell -docker exec -it homeassistant /bin/bash -``` - -[windows-keys]: https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-putty-on-digitalocean-droplets-windows-users - -### Generating SSH Keys - -Windows instructions for how to generate and use private/public keys with Putty are [here][windows-keys]. Instead of the droplet instructions, add the public key as per above instructions. - -Alternative instructions, for Mac, Windows and Linux can be found [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#platform-mac). - -Follow steps 1-4 under 'Generating a new SSH key' (The other sections are not applicable to Hass.io and can be ignored.) - -Step 3 in the link above, shows the path to the private key file `id_rsa` for your chosen operating system. Your public key, `id_rsa.pub`, is saved in the same folder. Next, select all text from text box "Public key for pasting into the authorized_keys file" and save it to the root of your USB drive as `authorized_keys`. diff --git a/website/versioned_docs/version-0.104.0/hassio_hass.md b/website/versioned_docs/version-0.104.0/hassio_hass.md deleted file mode 100644 index fc940dd9..00000000 --- a/website/versioned_docs/version-0.104.0/hassio_hass.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Hass.io <> Home Assistant integration development -sidebar_label: Integration development -id: version-0.104.0-hassio_hass -original_id: hassio_hass ---- - -These steps will help you connect your local Home Assistant to a remote Hass.io instance. You can then make changes locally to either the Hass.io component or the frontend and test it out against a real instance. - -For this guide, we're going to assume that you have an Hass.io instance up and running. If you don't, you can use the generic installation method to install it inside a [virtual machine](https://github.com/home-assistant/hassio-build/tree/master/install#install-hassio). - -## API Access - -To develop for the frontend, we're going to need API access to the supervisor. - -- Add our developer Add-on repository: https://github.com/home-assistant/hassio-addons-development -- Install the Add-on "Remote API proxy" - -For some API commands you need explicit the Home Assistant API token, but 99% of the functionality work with `Remote API proxy`. This token change sometimes but you can read the current legal token on host system with: -```shell -$ docker inspect homeassistant | grep HASSIO_TOKEN -``` - - ## Having Home Assistant connect to remote Hass.io - - The connection with the supervisor is hidden inside the host and is only accessible from applications running on the host. So to make it accessible for our Home Assistant instance we will need to route the connection to our computer running Home Assistant. We're going to do this by forwarding the API with "Remote API proxy" add-on. - -First, make sure Home Assistant will load the Hass.io component by adding `hassio:` to your `configuration.yaml` file. Next, we will need to tell the local Home Assistant instance how to connect to the remote Hass.io instance. We do this by setting the `HASSIO` and `HASSIO_TOKEN` environment variables when starting Home Assistant. Note that the `HASSIO` value is not the same as the one that we saw above and the `HASSIO_TOKEN` is available inside log output of "Remote API Add-on" (This changes every restart of the add-on!). - -```shell -HASSIO=:80 HASSIO_TOKEN= hass -``` - -Voila. Your local Home Assistant installation will now connect to a remote Hass.io instance. - -## Frontend development - -> This requires Home Assistant 0.71 or later. - -We need a couple more steps to do frontend development. First, make sure you have a Home Assistant frontend development set up ([instructions](frontend_index.md)). - -Update the Hass.io component configuration in your `configuration.yaml` to point at the frontend repository: - -```yaml -# configuration.yaml -hassio: - development_repo: /home/paulus/dev/hass/home-assistant-polymer -``` - -To build a local version of the Hass.io panel, go to the frontend repository and run: - -```shell -cd hassio -script/develop -``` - -Now start Home Assistant as discussed in the previous section and it will now connect to the remote Hass.io but show your local frontend. - -Once you have `script/develop` the hassio panel will be rebuilt whenever you make changes to the source files. diff --git a/website/versioned_docs/version-0.104.0/intent_conversation.md b/website/versioned_docs/version-0.104.0/intent_conversation.md deleted file mode 100644 index e2aae408..00000000 --- a/website/versioned_docs/version-0.104.0/intent_conversation.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Registering sentences -id: version-0.104.0-intent_conversation -original_id: intent_conversation ---- - -The conversation component handles incoming commands from the frontend and converts them to intents. It does this based on registered sentences. - -As a component, you can register sentences with the conversation component to allow it to be remote controlled. Refer to named slots by putting the slot name between curly braces: `{item}`. Use square brackets around (partial) words to mark them as optional. - -Example code: - -```python -async def async_setup(hass, config): - hass.components.conversation.async_register( - "MyCoolIntent", - ["I think that {object} is [very] cool", "Nothing is cooler than {object}"], - ) -``` - -If a sentence like "I think that beer is cool" comes in, the conversation component will generate an intent of type `MyCoolIntent` and with 1 slot, named `object` and value `beer`. diff --git a/website/versioned_docs/version-0.104.0/intent_firing.md b/website/versioned_docs/version-0.104.0/intent_firing.md deleted file mode 100644 index 71dbdaf6..00000000 --- a/website/versioned_docs/version-0.104.0/intent_firing.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Firing intents -id: version-0.104.0-intent_firing -original_id: intent_firing ---- - -When you fire an intent, you will get a response back or an error will be raised. It is up to the component to return the result to the user. - -Example code to handle an intent in Home Assistant. - -```python -from homeassistant.helpers import intent - -intent_type = "TurnLightOn" -slots = {"entity": {"value": "Kitchen"}} - -try: - intent_response = yield from intent.async_handle( - hass, "example_component", intent_type, slots - ) - -except intent.UnknownIntent as err: - _LOGGER.warning("Received unknown intent %s", intent_type) - -except intent.InvalidSlotInfo as err: - _LOGGER.error("Received invalid slot data: %s", err) - -except intent.IntentError: - _LOGGER.exception("Error handling request for %s", intent_type) -``` - -The intent response is an instance of `homeassistant.helpers.intent.IntentResponse`. - -| Name | Type | Description | -| ---- | ---- | ----------- | -| `intent` | Intent | Instance of intent that triggered response. | -| `speech` | Dictionary | Speech responses. Each key is a type. Allowed types are `plain` and `ssml`. | -| `card` | Dictionary | Card responses. Each key is a type. | - -Speech dictionary values: - -| Name | Type | Description | -| ---- | ---- | ----------- | -| `speech` | String | The text to say -| `extra_data` | Any | Extra information related to this speech. - -Card dictionary values: - -| Name | Type | Description | -| ---- | ---- | ----------- | -| `title` | String | The title of the card -| `content` | Any | The content of the card diff --git a/website/versioned_docs/version-0.104.0/intent_handling.md b/website/versioned_docs/version-0.104.0/intent_handling.md deleted file mode 100644 index 866d7da5..00000000 --- a/website/versioned_docs/version-0.104.0/intent_handling.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Handling intents -id: version-0.104.0-intent_handling -original_id: intent_handling ---- - -Any component can register to handle intents. This allows a single component to handle intents fired from multiple voice assistants. - -A component has to register an intent handler for each type that it wants to handle. Intent handlers have to extend `homeassistant.helpers.intent.IntentHandler` - -```python -import asyncio -from homeassistant.helpers import intent - -DATA_KEY = "example_key" - - -@asyncio.coroutine -def async_setup(hass, config): - hass.data[DATA_KEY] = 0 - intent.async_register(hass, CountInvocationIntent()) - - -class CountInvocationIntent(intent.IntentHandler): - """Handle CountInvocationIntent intents.""" - - # Type of intent to handle - intent_type = "CountInvocationIntent" - - # Optional. A validation schema for slots - # slot_schema = { - # 'item': cv.string - # } - - @asyncio.coroutine - def async_handle(self, intent_obj): - """Handle the intent.""" - intent_obj.hass.data[DATA_KEY] += 1 - - response = intent_obj.create_response() - response.async_set_speech( - f"This intent has been invoked {intent_obj.hass.data[DATA_KEY]} times" - ) - return response -``` diff --git a/website/versioned_docs/version-0.104.0/internationalization_backend_localization.md b/website/versioned_docs/version-0.104.0/internationalization_backend_localization.md deleted file mode 100644 index 65342ec8..00000000 --- a/website/versioned_docs/version-0.104.0/internationalization_backend_localization.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Backend Localization -id: version-0.104.0-internationalization_backend_localization -original_id: internationalization_backend_localization ---- - -## Translation Strings -Platform translation strings are stored as JSON in the [home-assistant](https://github.com/home-assistant/home-assistant) repository. These files must be located adjacent to the component/platform they belong to. Components must have their own directory, and the file is simply named `strings.json` in that directory. For platforms, they are named `strings..json` in the platform directory. This file will contain the different strings that will be translatable. - -In order to test changes to translation files, the translation strings must be compiled into Home Assistant’s translation directories by running the following script: - -```shell -$ script/translations_develop -``` - -After the pull request with the strings file is merged into the `dev` branch, the strings will be automatically uploaded to Lokalise, where contributors can submit translations. The translated strings in Lokalise will be periodically pulled in to the home-assistant repository. - -## States Localization -The first step when localizing platform states is to ensure that the states defined in the actual platform code are defined in `snake_case`. The states should not contain capital letters or spaces. Next, the strings file needs to be created. The states should exist under the `state` key, and map the backend state keys to their English translations. [The season sensor localization](https://github.com/home-assistant/home-assistant/pull/12453/commits/bb2f328ce10c3867990e34a88da64e2f8dc7a5c4) is a good example. - -## Configuration Flow Localization -The translation strings for the configuration flow handler are defined under the `config` key. An example strings file below describes the different supported keys: - -```json -{ - "config": { - "title": "This title is shown in the integrations list", - "step": { - "init": { - "title": "The user visible title of the `init` step.", - "description": "Markdown that is shown with the step.", - "data": { - "api_key": "The label for the `api_key` input field" - } - } - }, - "error": { - "invalid_api_key": "This message will be displayed if `invalid_api_key` is returned as a flow error." - }, - "abort": { - "stale_api_key": "This message will be displayed if `stale_api_key` is returned as the abort reason." - } - } -} -``` diff --git a/website/versioned_docs/version-0.104.0/internationalization_translation.md b/website/versioned_docs/version-0.104.0/internationalization_translation.md deleted file mode 100644 index adc2f4cc..00000000 --- a/website/versioned_docs/version-0.104.0/internationalization_translation.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Translation -id: version-0.104.0-internationalization_translation -original_id: internationalization_translation ---- - -Translations for Home Assistant are managed through [Lokalise](https://lokalise.co/), an online translation management tool. Our translations are split between two projects, a backend project for platform-specific translations, and a frontend project for UI translations. Click the links below to join both projects! Even if your language is completely translated, extra proofreading is a big help! Please feel free to review the existing translations, and vote for alternatives that might be more appropriate. - -- [Join the frontend translation team](https://lokalise.co/signup/3420425759f6d6d241f598.13594006/all/) -- [Join the backend translation team](https://lokalise.co/signup/130246255a974bd3b5e8a1.51616605/all/) -- [Join the iOS translation team](https://lokalise.co/signup/834452985a05254348aee2.46389241/all/) -- [Join the Android translation team](https://lokalise.com/public/145814835dd655bc5ab0d0.36753359/) - -For more information about the translation workflow, please see the [Lokalise translation workflow documents](https://docs.lokalise.co/category/iOzEuQPS53-for-team-leads-and-translators). - -> The translation of the Home Assistant frontend is still a work in progress. More phrases will be available for translation soon. - -## Translation placeholders - -Some translation strings will contain special placeholders that will be replaced later. Placeholders shown in square brackets `[]` are [Lokalise key references](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing). These are primarily used to link translation strings that will be duplicated. Different languages may not have the same duplicates as English, and are welcome to link duplicate translations that are not linked in English. Placeholders shown in curly brackets `{}` are [translation arguments](https://formatjs.io/guides/message-syntax/) that will be replaced with a live value when Home Assistant is running. Any translation argument placeholders present in the original string must be included in the translated string. These may include special syntax for defining plurals or other replacement rules. The linked format.js guide explains the syntax for adding plural definitions and other rules. - -## Rules -1. Only native speakers should submit translations. -2. Stick to [Material Design guidelines](https://material.io/guidelines/style/writing.html). -3. Don't translate or change proper nouns like `Home Assistant`, `Hass.io` or `Hue`. -4. For a region specific translation, keys that will be the same as the base translation should be filled with `[VOID]`. These will be replaced during our translation build process. -5. Translations under the `state_badge` keys will be used for the notification badge display. These translations should be short enough to fit in the badge label without overflowing. This can be tested in the Home Assistant UI either by editing the label text with your browsers development tools, or by using the States states dev tool icon developer tool in the Home Assistant UI. In the UI, enter a new entity ID (`device_tracker.test`), and enter the text you want to test in state. -6. If text will be duplicated across different translation keys, make use of the Lokalise key reference feature where possible. The base translation provides examples of this underneath the `states` translations. Please see the [Lokalise key referencing](https://docs.lokalise.com/en/articles/1400528-key-referencing) documentation for more details. - -## Adding a new language -If your language is not listed you can request it at [GitHub](https://github.com/home-assistant/home-assistant-polymer/issues/new). Please provide both the English name and the native name for your language. For example: -``` -English Name: German -Native Name: Deutsch -``` - -> Region specific translations (`en-US`, `fr-CA`) will only be included if translations for that region need to differ from the base language translation. - -### Maintainer steps to add a new language -1. Language tags have to follow [BCP 47](https://tools.ietf.org/html/bcp47). A list of most language tags can be found here: [IANA sutbtag registry](http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry). Examples: `fr`, `fr-CA`, `zh-Hans`. Only include the country code if country specific overrides are being included, and the base language is already translated. -2. Add the language tag and native name in `src/translations/translationMetadata.json`. Examples: "Français", "Français (CA)" -3. Add the new language in Lokalize. -Note: Sometimes you have to change the tag in Lokalise (Language -> Language settings -> custom ISO code). diff --git a/website/versioned_docs/version-0.104.0/lovelace_custom_card.md b/website/versioned_docs/version-0.104.0/lovelace_custom_card.md deleted file mode 100644 index b8a1227e..00000000 --- a/website/versioned_docs/version-0.104.0/lovelace_custom_card.md +++ /dev/null @@ -1,249 +0,0 @@ ---- -title: Lovelace: Custom Cards -id: version-0.104.0-lovelace_custom_card -original_id: lovelace_custom_card ---- - -[Lovelace](https://www.home-assistant.io/lovelace/) is our new approach to defining your user interface for Home Assistant. We offer a lot of built-in cards, but you're not just limited to the ones that we decided to include in the Lovelace UI. You can build and use your own! - -## API - -You define your custom card as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). It's up to you to decide how to render your DOM inside your element. You can use Polymer, Angular, Preact or any other popular framework (except for React – [more info on React here](https://custom-elements-everywhere.com/#react)). - -```js -const element = document.createElement('some-custom-card'); -``` - -Home Assistant will call `setConfig(config)` when the configuration changes (rare). If you throw an exception if the configuration is invalid, Lovelace will render an error card to notify the user. - -```js -try { - element.setConfig(config); -} catch (err) { - showErrorCard(err.message, config); -} -``` - -Home Assistant will set the `hass` property when the state of Home Assistant changes (frequent). Whenever the state changes, the component will have to update itself to represent the latest state. - -```js -element.hass = hass; -``` - -Your card can define a `getCardSize` method that returns the size of your card as a number. A height of 1 is equivalent to 50 pixels. This will help Home Assistant distribute the cards evenly over the columns. A card size of `1` will be assumed if the method is not defined. - -```js -if ('getCardSize' in element) { - return element.getCardSize(); -} else { - return 1; -} -``` - -## Defining your card - -Create a new file in your Home Assistant config dir as `/www/content-card-example.js` and put in the following contents: - -```js -class ContentCardExample extends HTMLElement { - set hass(hass) { - if (!this.content) { - const card = document.createElement('ha-card'); - card.header = 'Example card'; - this.content = document.createElement('div'); - this.content.style.padding = '0 16px 16px'; - card.appendChild(this.content); - this.appendChild(card); - } - - const entityId = this.config.entity; - const state = hass.states[entityId]; - const stateStr = state ? state.state : 'unavailable'; - - this.content.innerHTML = ` - The state of ${entityId} is ${stateStr}! -

- - `; - } - - setConfig(config) { - if (!config.entity) { - throw new Error('You need to define an entity'); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return 3; - } -} - -customElements.define('content-card-example', ContentCardExample); -``` - -## Referencing your new card - -In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `/www` directory, it will be accessible in your browser via the url `/local/` (if you have recently added the www folder you will need to re-start Home Assistant for files to be picked up). - -```yaml -# Example Lovelace configuration -resources: - - url: /local/content-card-example.js - type: js -views: -- name: Example - cards: - - type: "custom:content-card-example" - entity: input_boolean.switch_tv -``` - -## Advanced example - -Resources to load in Lovelace can be imported as a JS script, an HTML import or as a JS module import. Below is an example of a custom card using JS modules that does all the fancy things. - -![Screenshot of the wired card](/img/en/frontend/lovelace-ui-custom-card-screenshot.png) - -Create a new file in your Home Assistant config dir as `/www/wired-cards.js` and put in the following contents: - -```js -import "https://unpkg.com/wired-card@0.8.1/wired-card.js?module"; -import "https://unpkg.com/wired-toggle@0.8.0/wired-toggle.js?module"; -import { - LitElement, - html, - css -} from "https://unpkg.com/lit-element@2.0.1/lit-element.js?module"; - -function loadCSS(url) { - const link = document.createElement("link"); - link.type = "text/css"; - link.rel = "stylesheet"; - link.href = url; - document.head.appendChild(link); -} - -loadCSS("https://fonts.googleapis.com/css?family=Gloria+Hallelujah"); - -class WiredToggleCard extends LitElement { - static get properties() { - return { - hass: {}, - config: {} - }; - } - - render() { - return html` - - ${this.config.entities.map(ent => { - const stateObj = this.hass.states[ent]; - return stateObj - ? html` -
- ${stateObj.attributes.friendly_name} - -
- ` - : html` -
Entity ${ent} not found.
- `; - })} -
- `; - } - - setConfig(config) { - if (!config.entities) { - throw new Error("You need to define entities"); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return this.config.entities.length + 1; - } - - _toggle(state) { - this.hass.callService("homeassistant", "toggle", { - entity_id: state.entity_id - }); - } - - static get styles() { - return css` - :host { - font-family: "Gloria Hallelujah", cursive; - } - wired-card { - background-color: white; - padding: 16px; - display: block; - font-size: 18px; - } - .state { - display: flex; - justify-content: space-between; - padding: 8px; - align-items: center; - } - .not-found { - background-color: yellow; - font-family: sans-serif; - font-size: 14px; - padding: 8px; - } - wired-toggle { - margin-left: 8px; - } - `; - } -} -customElements.define("wired-toggle-card", WiredToggleCard); -``` - -And for your configuration: - -```yaml -# Example Lovelace configuration -resources: - - url: /local/wired-cards.js - type: module -views: -- name: Example - cards: - - type: "custom:wired-toggle-card" - entities: - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_livingroom - - input_boolean.switch_tv -``` - -## Recommended Design Elements - -We are currently migrating from using Paper Elements to MWC (Material Web Component) Elements. - -If an element exists in the below repository for MWC. We recommended using it. - -- [MWC (Material Web Components)](https://material-components.github.io/material-components-web-components/demos/index.html) - -If an element does not exist in MWC, we default to using Paper Elements. - -- [Paper Elements](https://www.webcomponents.org/collection/PolymerElements/paper-elements) - -## Advanced Resources - -Community Maintained Boilerplate Card - Advanced Template (Typescript, Rollup, Linting, etc.) - -- [Boilerplate Card](https://github.com/custom-cards/boilerplate-card) - -Developer Documentation for [HACS](https://hacs.xyz/) (Home Assistant Community Store). - -- [HACS Plugin Docs](https://hacs.xyz/docs/publish/plugin) diff --git a/website/versioned_docs/version-0.104.0/maintenance.md b/website/versioned_docs/version-0.104.0/maintenance.md deleted file mode 100644 index 672f263e..00000000 --- a/website/versioned_docs/version-0.104.0/maintenance.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Maintenance -id: version-0.104.0-maintenance -original_id: maintenance ---- - -This page documents a couple of points for maintaining the Home Assistant code. Most of the tasks don't need to be performed on a regular base thus the steps, used tools, or details are preserved here. - -## Source code - -### Line separator - -People are using various operating systems to develop components and platforms for Home Assistant. This could lead to different line endings on file. We prefer `LN`. Especially Microsoft Windows tools tend to use `CRLF`. - -```shell -$ find homeassistant -name "*.py" -exec file {} \; | grep BOM -$ find homeassistant -name "*.py" -exec file {} \; | grep CRLF -``` - -To fix the line separator, use `dos2unix` or `sed`. - -```shell -$ dos2unix homeassistant/components/notify/kodi.py -``` - -### File permissions - -Most files don't need to the be executable. `0644` is fine. - -### Dependencies - -A lot of components and platforms depends on third-party Python modules. The dependencies which are stored in the `requirements_all.txt` files can be tracked with [`pur`](https://pypi.org/project/pur/) or [`pip-upgrader`](https://github.com/simion/pip-upgrader). - -If you update the requirements of a component/platform by updating `manifest.json`, run the provided script to update the `requirements_*.txt` file(s). - -```shell -$ script/gen_requirements_all.py -``` - -Start a test run of Home Assistant. If that was successful, include all files in a Pull Request. Add a short summary of the changes, a sample configuration entry, details about the tests you performed to ensure the update works, and other useful information to the description. - - -## Documentation - -- Merge `current` into `next` on a regular base. -- Optimize the images. - diff --git a/website/versioned_docs/version-0.104.0/reproduce_state_index.md b/website/versioned_docs/version-0.104.0/reproduce_state_index.md deleted file mode 100644 index 524c1d01..00000000 --- a/website/versioned_docs/version-0.104.0/reproduce_state_index.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Reproduce State / Scene support -id: version-0.104.0-reproduce_state_index -original_id: reproduce_state_index ---- - -Home Assistant has support for scenes. Scenes are a collection of (partial) entity states. When a scene is activated, Home Assistant will try to call the right services to get the specified scenes in their specified state. - -Integrations are responsible for adding support to Home Assistant to be able to call the right services to reproduce the states in a scene. - -## Adding support - -The quickest way to add reproduce state support to a new integration is by using our built-in scaffold template. From a Home Assistant dev environment, run `python3 -m script.scaffold reproduce_state` and follow the instructions. - -If you prefer to go the manual route, create a new file in your integration folder called `reproduce_state.py` and implement the following method: - -```python -import asyncio -from typing import Iterable, Optional -from homeassistant.core import Context, State -from homeassistant.helpers.typing import HomeAssistantType - - -async def async_reproduce_states( - hass: HomeAssistantType, states: Iterable[State], context: Optional[Context] = None -) -> None: - """Reproduce component states.""" - # TODO reproduce states -``` diff --git a/website/versioned_docs/version-0.105.0/app_integration_notifications.md b/website/versioned_docs/version-0.105.0/app_integration_notifications.md deleted file mode 100644 index cd0ede75..00000000 --- a/website/versioned_docs/version-0.105.0/app_integration_notifications.md +++ /dev/null @@ -1,239 +0,0 @@ ---- -title: Push Notifications -id: version-0.105.0-app_integration_notifications -original_id: app_integration_notifications ---- - -The `mobile_app` component has a notify platform built in that allows for a generic way to send push notifications to your users without requiring installation of an external custom component. - -## Enabling push notifications - -To enable the notify platform for your application, you must set two keys in the `app_data` object during the initial registration or later update of an existing registration. - -| Key | Type | Description -| --- | ---- | ----------- -| `push_token` | string | A push notification token unique to your users device. For example, this could be a APNS token or a FCM Instance ID/token. -| `push_url` | string | The URL on your server that push notifications will be HTTP POSTed to. - -You should advise the user to restart Home Assistant after you set these keys in order for them to see the notify target. It will have the format `notify.mobile_app_`. - -## Deploying a server component - -The notify platform doesn't concern itself with how to notify your users. It simply forwards a notification to your external server where you should actually handle the request. -This approach allows you to maintain full control over your push notification infrastructure. - -See the next section of this document for an example server implementation of a push notification forwarder that uses Firebase Cloud Functions and Firebase Cloud Messaging. - -Your server should accept a HTTP POST payload like this: - -```json -{ - "message": "Hello World", - "title": "Test message sent via mobile_app.notify", - "push_token": "my-secure-token", - "registration_info": { - "app_id": "io.home-assistant.iOS", - "app_version": "1.0.0", - "os_version": "12.2" - }, - "data": { - "key": "value" - } -} -``` - -It should respond with a 201 status code assuming the notification was queued for delivery successfully. - -### Errors - -If an error occurs you should return a description of what went wrong with a status code _other than_ 201 or 429. An error response must be a JSON object and can contain one of the following keys: - -| Key | Type | Description -| --- | ---- | ----------- -| `errorMessage` | string | If provided, it will be appended to a preset error message. For example, if `errorMessage` is "Could not communicate with Apple" it will be output in the log like "Internal server error, please try again later: Could not communicate with Apple" -| `message` | string | If provided, it will be output directly to the logs at the warning log level. - -No matter what key you use, you should try to be as descriptive as possible about what went wrong and, if possible, how the user can fix it. - -### Rate limits - -The notify platform also supports exposing rate limits to users. Home Assistant suggests you implement a conservative rate limit to keep your costs low and also so that users don't overload themselves with too many notifications. -For reference, Home Assistant Companion has a maximum sendable notifications per 24 hours of 150 notifications. The rate limit resets for all users at midnight, UTC. You of course are free to use whatever configuration for your own rate limiting. - -If you choose to implement rate limiting, your successful server response should look like the following: - -```json -{ - "rateLimits": { - "successful": 1, - "errors": 5, - "maximum": 150, - "resetsAt": "2019-04-08T00:00:00.000Z" - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `successful` | integer | The number of successful push notifications the user has sent during the rate limit period. -| `errors` | integer | The number of failed push notifications the user has sent during the rate limit period. -| `maximum` | integer | The maximum number of push notifications the user can send during the users rate limit period. -| `resetsAt` | ISO8601 timestamp | The timestamp that the users rate limit period expires at. Must be provided in the UTC timezone. - -The rate limits will be output to the log at the warning log level after every notification is successfully sent. Home Assistant will also output the exact time remaining until the rate limit period resets. - -Once the user hits their maximum amount of notifications sent in the rate limit period, you should start responding with a 429 status code until the rate limit period expires. The response object can optionally contain a key, `message` which will be output to the Home Assistant log instead of the standard error message. - -The notify platform does not itself implement any kind of rate limit protections. Users will be able to keep sending you notifications, so you should reject them with a 429 status code as early in your logic as possible. - -## Example server implementation -The below code is a Firebase Cloud Function that forwards notifications to Firebase Cloud Messaging. To deploy this, you should create a new Firestore database named `rateLimits`. Then, you can deploy the following code. -Also, ensure that you have properly configured your project with the correct authentication keys for APNS and FCM. - -```javascript -'use strict'; - -const functions = require('firebase-functions'); -const admin = require('firebase-admin'); -admin.initializeApp(); - -var db = admin.firestore(); - -const MAX_NOTIFICATIONS_PER_DAY = 150; - -exports.sendPushNotification = functions.https.onRequest(async (req, res) => { - console.log('Received payload', req.body); - var today = getToday(); - var token = req.body.push_token; - var ref = db.collection('rateLimits').doc(today).collection('tokens').doc(token); - - var payload = { - notification: { - body: req.body.message, - }, - token: token, - }; - - if(req.body.title) { - payload.notification.title = req.body.title; - } - - if(req.body.data) { - if(req.body.data.android) { - payload.android = req.body.data.android; - } - if(req.body.data.apns) { - payload.apns = req.body.data.apns; - } - if(req.body.data.data) { - payload.data = req.body.data.data; - } - if(req.body.data.webpush) { - payload.webpush = req.body.data.webpush; - } - } - - console.log('Notification payload', JSON.stringify(payload)); - - var docExists = false; - var docData = { - deliveredCount: 0, - errorCount: 0, - totalCount: 0, - }; - - try { - let currentDoc = await ref.get(); - docExists = currentDoc.exists; - if(currentDoc.exists) { - docData = currentDoc.data(); - } - } catch(err) { - console.error('Error getting document!', err); - return handleError(res, 'getDoc', err); - } - - if(docData.deliveredCount > MAX_NOTIFICATIONS_PER_DAY) { - return res.status(429).send({ - errorType: 'RateLimited', - message: 'The given target has reached the maximum number of notifications allowed per day. Please try again later.', - target: token, - rateLimits: getRateLimitsObject(docData), - }); - } - - docData.totalCount = docData.totalCount + 1; - - var messageId; - try { - messageId = await admin.messaging().send(payload); - docData.deliveredCount = docData.deliveredCount + 1; - } catch(err) { - docData.errorCount = docData.errorCount + 1; - await setRateLimitDoc(ref, docExists, docData, res); - return handleError(res, 'sendNotification', err); - } - - console.log('Successfully sent message:', messageId); - - await setRateLimitDoc(ref, docExists, docData, res); - - return res.status(201).send({ - messageId: messageId, - sentPayload: payload, - target: token, - rateLimits: getRateLimitsObject(docData), - }); - -}); - -async function setRateLimitDoc(ref, docExists, docData, res) { - try { - if(docExists) { - console.log('Updating existing doc!'); - await ref.update(docData); - } else { - console.log('Creating new doc!'); - await ref.set(docData); - } - } catch(err) { - if(docExists) { - console.error('Error updating document!', err); - } else { - console.error('Error creating document!', err); - } - return handleError(res, 'setDocument', err); - } - return true; -} - -function handleError(res, step, incomingError) { - if (!incomingError) return null; - console.error('InternalError during', step, incomingError); - return res.status(500).send({ - errorType: 'InternalError', - errorStep: step, - message: incomingError.message, - }); -} - -function getToday() { - var today = new Date(); - var dd = String(today.getDate()).padStart(2, '0'); - var mm = String(today.getMonth() + 1).padStart(2, '0'); - var yyyy = today.getFullYear(); - return yyyy + mm + dd; -} - -function getRateLimitsObject(doc) { - var d = new Date(); - return { - successful: (doc.deliveredCount || 0), - errors: (doc.errorCount || 0), - total: (doc.totalCount || 0), - maximum: MAX_NOTIFICATIONS_PER_DAY, - remaining: (MAX_NOTIFICATIONS_PER_DAY - doc.deliveredCount), - resetsAt: new Date(d.getFullYear(), d.getMonth(), d.getDate()+1) - }; -} -``` diff --git a/website/versioned_docs/version-0.105.0/app_integration_sensors.md b/website/versioned_docs/version-0.105.0/app_integration_sensors.md deleted file mode 100644 index bd90cd42..00000000 --- a/website/versioned_docs/version-0.105.0/app_integration_sensors.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Sensors -id: version-0.105.0-app_integration_sensors -original_id: app_integration_sensors ---- - -The `mobile_app` component supports exposing custom sensors that can be managed entirely via your app. - -## Registering a sensor - -All sensors must be registered before they can get updated. You can only register one sensor at a time, unlike updating sensors. - -To register a sensor, make a request to the webhook like this: - -```json -{ - "data": { - "attributes": { - "foo": "bar" - }, - "device_class": "battery", - "icon": "mdi:battery", - "name": "Battery State", - "state": "12345", - "type": "sensor", - "unique_id": "battery_state", - "unit_of_measurement": "%" - }, - "type": "register_sensor" -} -``` - -The valid keys are: - -| Key | Type | Required | Description | -|---------------------|-------------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| attributes | object | No | Attributes to attach to the sensor | -| device_class | string | No | One of the valid device classes. [Binary Sensor Classes](https://www.home-assistant.io/components/binary_sensor/#device-class), [Sensor Classes](https://www.home-assistant.io/components/sensor/#device-class) | -| icon | Material Design Icon (string) | No | Must be prefixed `mdi:`. If not provided, default value is `mdi:cellphone` | -| name | string | Yes | The name of the sensor | -| state | bool, float, int, string | Yes | The state of the sensor | -| type | string | Yes | The type of the sensor. Must be one of `binary_sensor` or `sensor` | -| unique_id | string | Yes | An identifier unique to this installation of your app. You'll need this later. Usually best when its a safe version of the sensor name | -| unit_of_measurement | string | No | The unit of measurement for the sensor | - -Sensors will appear as soon as they are registered. - -## Updating a sensor - -Once a sensor has been registered, you need to update it. This is very similar to registering it, but you can update all your sensors at the same time. - -For example, to update the sensor we registered above, you would send this: - -```json -{ - "data": [ - { - "attributes": { - "hello": "world" - }, - "icon": "mdi:battery", - "state": 123, - "type": "sensor", - "unique_id": "battery_state" - } - ], - "type": "update_sensor_states" -} -``` - -Only some of the keys are allowed during updates: - -| Key | Type | Required | Description | -|---------------------|-------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------| -| attributes | object | No | Attributes to attach to the sensor | -| icon | Material Design Icon (string) | No | Must be prefixed `mdi:` | -| state | bool, float, int, string | Yes | The state of the sensor | -| type | string | Yes | The type of the sensor. Must be one of `binary_sensor` or `sensor` | -| unique_id | string | Yes | An identifier unique to this installation of your app. You'll need this later. Usually best when its a safe version of the sensor name | - diff --git a/website/versioned_docs/version-0.105.0/dev_101_services.md b/website/versioned_docs/version-0.105.0/dev_101_services.md deleted file mode 100644 index b69e90af..00000000 --- a/website/versioned_docs/version-0.105.0/dev_101_services.md +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: Integration Services -sidebar_label: Custom Services -id: version-0.105.0-dev_101_services -original_id: dev_101_services ---- - -Home Assistant provides ready-made services for a lot of things, but it doesn't always cover everything. Instead of trying to change Home Assistant, it is preferred to add it as a service under your own integration first. Once we see a pattern in these services, we can talk about generalizing them. - -This is a simple "hello world" example to show the basics of registering a service. To use this example, create the file `/custom_components/hello_service/__init__.py` and copy the below example code. - -Services can be called from automations and from the service "Developer tools" in the frontend. - -```python -DOMAIN = "hello_service" - -ATTR_NAME = "name" -DEFAULT_NAME = "World" - - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - def handle_hello(call): - """Handle the service call.""" - name = call.data.get(ATTR_NAME, DEFAULT_NAME) - - hass.states.set("hello_service.hello", name) - - hass.services.register(DOMAIN, "hello", handle_hello) - - # Return boolean to indicate that initialization was successfully. - return True -``` - -Load the integration by adding the following to your `configuration.yaml`. When your component is loaded, a new service should be available to call. - -```yaml -# configuration.yaml entry -hello_service: -``` - -Open the frontend and in the sidebar, click the first icon in the developer tool section. This will open the Call Service developer tool. On the right, find your service and click on it. This will automatically fill in the correct values. - -Pressing "Call Service" will now call your service without any parameters. This will cause your service to create a state with the default name 'World'. If you want to specify the name, you have to specify parameters. Add the following JSON as Service Data and press "Call Service again". - -```json -{ - "name": "Planet" -} -``` - -The service will now overwrite the previous state with "Planet". - -## Service descriptions - -Adding services is only useful if users know about them. In Home Assistant we use a `services.yaml` as part of your integration to describe the services. - -Services are published under the domain name of your integration, so in `services.yaml` we only use the service name as the base key. - -```yaml -# Example services.yaml entry - -set_speed: - # Description of the service - description: Sets fan speed. - # Different fields that your service accepts - fields: - # Key of the field - entity_id: - # Description of the field - description: Name(s) of the entities to set - # Example value that can be passed for this field - example: "fan.living_room" - speed: - description: Speed setting - example: "low" -``` - -## Entity Services - -Sometimes you want to provide extra services to control your entities. For example, the Sonos integration provides services to group and ungroup devices. Entity services are special because there are many different ways a user can specify entities. It can use areas, a group or a list of entities. - -You need to register entity services in your platforms, like `/media_player.py`. These services will be made available under your domain and not the media player domain. Example code: - -```python -from homeassistant.helpers import config_validation as cv, entity_platform, service - -async def async_setup_entry(hass, entry): - """Set up the media player platform for Sonos.""" - - platform = entity_platform.current_platform.get() - - # This will call Entity.set_sleep_timer(sleep_time=VALUE) - platform.async_register_entity_service( - SERVICE_SET_TIMER, - { - vol.Required('sleep_time'): cv.time_period, - }, - "set_sleep_timer", - ) -``` - -If you need more control over the service call, you can also pass an async function that instead of `"set_sleep_timer"`: - -```python -async def custom_set_sleep_timer(entity, service_call): - await entity.set_sleep_timer(service_call.data['sleep_time']) -``` diff --git a/website/versioned_docs/version-0.105.0/device_automation_condition.md b/website/versioned_docs/version-0.105.0/device_automation_condition.md deleted file mode 100644 index 6ebfd462..00000000 --- a/website/versioned_docs/version-0.105.0/device_automation_condition.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Device Conditions -sidebar_label: Conditions -id: version-0.105.0-device_automation_condition -original_id: device_automation_condition ---- - -Device conditions allow a user to check if a certain condition is met. Examples are is a light on or is the floor wet. - -Device conditions are defined as dictionaries. These dictionaries are created by your integration and are passed to your integration to create a function that checks the condition. - -Device conditions can be provided by the integration that provides the device (e.g. ZHA, deCONZ) or the entity integrations that the device has entities with (e.g. light, humidity sensor). -An example of the latter could be to check if a light is on or the floor is wet. - -Home Assistant includes a template to get started with device conditions. To get started, run inside a development environment `python3 -m script.scaffold device_condition`. - -The template will create a new file `device_condition.py` in your integration folder and a matching test file. The file contains the following functions and constants: - -## `CONDITION_SCHEMA` - -This is the schema for conditions. The base schema should be extended from `homeassistant.helpers.config_validation.DEVICE_CONDITION_BASE_SCHEMA`. - -## `async async_get_conditions(hass, device_id)` - -Return a list of conditions that this device supports. - -## `async async_condition_from_config(config, config_validation)` - -Create a condition function from a function. The condition functions should be an async-friendly callback that evaluates the condition and returns a `bool`. diff --git a/website/versioned_docs/version-0.105.0/documentation_standards.md b/website/versioned_docs/version-0.105.0/documentation_standards.md deleted file mode 100644 index d099687d..00000000 --- a/website/versioned_docs/version-0.105.0/documentation_standards.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Standards -id: version-0.105.0-documentation_standards -original_id: documentation_standards ---- - -To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation. - -## General Documentation - -* The language of the documentation should be American-English. -* Don't put two spaces after a period and avoid the "Oxford comma". -* There is no limit for the line length. You are allowed to write in a flowing text style. This will make it easier to use the GitHub online editor in the future. -* Be objective and not gender favoring, polarizing, race related or religion inconsiderate. -* The case of brand names, services, protocols, integrations and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select". -* Do not use ALL CAPITALS for emphasis - use italics instead. - -## Integration and Platform Pages - -* The **Configuration Variables** section must use the `{% configuration %}` tag. -* Configuration variables must document the requirement status (`false` or `true`). -* Configuration variables must document the default value, if any. -* Configuration variables must document the accepted value types (see [Configuration variables details](documentation_create_page.md#configuration)). - * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`). -* Use YAML sequence syntax in the sample code if it is supported. -* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated. - * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`. - * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note. -* Integration and platform names should be a link to their respective documentation pages. - -Example configuration block - -```yaml -{% configuration %} -some_key: - description: This is a description of what this key is for. - required: false - type: string - default: Optional default value - leave out if there isn't one -{% endconfiguration %} -``` - -## Templates - -* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the `{% raw %}` tag. -* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`. -* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)): - * `friendly_name` - * Single-line templates: - * `value_template` - * `level_template` - * `icon_template` - * Children of `data_template` -* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks): - * Strings inside of templates: - * States - * Entity IDs - * `unit_of_measurement` -* No whitespace around pipe character (`|`) for Jinja2 filters. -* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}). -* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}). -* Do not quote values for: - * `device_class` - * `platform` - * `condition` - * `service` - -## Renaming Pages - -It can happen that an integration or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old integration/platform name, to the page in a [note](/developers/documentation/create_page/#html). - -```text ---- -... -redirect_from: /getting-started/android/ ---- -``` - -Adding a redirect also applies if you move content around in the [documentation](https://www.home-assistant.io/docs/). - -## Single vs. Double Quotation Marks - -Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required). - -### Examples - -#### Double Quotes Outside, Single Quotes Inside (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}" -``` - -#### Single Quotes Outside, Double Quotes Inside (Invalid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}' -``` - -#### Multi-Line Template (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: >- - {% if trigger.to_state.name == 'Dale\'s Bedroom' %} - Someone's in your base, killing your noobs! - {% else %} - It's just another door. - {% endif %} -``` diff --git a/website/versioned_docs/version-0.105.0/entity_cover.md b/website/versioned_docs/version-0.105.0/entity_cover.md deleted file mode 100644 index f118c021..00000000 --- a/website/versioned_docs/version-0.105.0/entity_cover.md +++ /dev/null @@ -1,188 +0,0 @@ ---- -title: Cover Entity -sidebar_label: Cover -id: version-0.105.0-entity_cover -original_id: entity_cover ---- - -A cover entity is a device that controls an opening or cover, such as a garage door and window shade. Derive entity platforms from [`homeassistant.components.cover.CoverDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/cover/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -### Platform Properties (to be implemented by deriving platform classes) - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| current_cover_position | int | None | The current position of cover where 0 means closed and 100 is fully open. Required with `SUPPORT_SET_POSITION`. -| current_cover_tilt_position | int | None | The current tilt position of the cover where 0 means closed/no tilt and 100 means open/maximum tilt. Required with `SUPPORT_SET_TILT_POSITION` -| is_opening | bool | None | If the cover is opening or not. Used to determine `state`. -| is_closing | bool | None | If the cover is closing or not. Used to determine `state`. -| is_closed | bool | `NotImplementedError()` | If the cover is closed or not. if the state is unknown, return `None`. Used to determine `state`. - -### Entity Properties (base class properties which may be overridden) - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| device_class | string | None | Describes the type/class of the cover. Must be `None` or one of the valid values from the table below. -| supported_features | int (bitwise) | Value determined from `current_cover_position` and `current_cover_tilt_position` | Describes the supported features. See the related table below for details. - -### Device Classes -| Constant | Description -|----------|-----------------------| -| `DEVICE_CLASS_AWNING` | Control of an awning, such as an exterior retractible window, door, or patio cover. -| `DEVICE_CLASS_BLIND` | Control of blinds, which are linked slats that expand or collapse to cover an opening or may be tilted to partially cover an opening, such as window blinds. -| `DEVICE_CLASS_CURTAIN` | Control of curtains or drapes, which is often fabric hung above a window or door that can be drawn open. -| `DEVICE_CLASS_DAMPER` | Control of a mechanical damper that reduces air flow, sound, or light. -| `DEVICE_CLASS_DOOR` | Control of a door or gate that provides access to an area. -| `DEVICE_CLASS_GARAGE` | Control of a garage door that provides access to a garage. -| `DEVICE_CLASS_SHADE` | Control of shades, which are a continuous plane of material or connected cells that expanded or collapsed over an opening, such as window shades. -| `DEVICE_CLASS_SHUTTER` | Control of shutters, which are linked slats that swing out/in to cover an opening or may be tilted to partially cover an opening, such as indoor or exterior window shutters. -| `DEVICE_CLASS_WINDOW` | Control of a physical window that opens and closes or may tilt. - -### States -| Constant | Description -|----------|------------------------| -| `STATE_OPENING` | The cover is in the process of opening to reach a set position. -| `STATE_OPEN` | The cover has reached the open position. -| `STATE_CLOSING` | The cover is in the process of closing to reach a set position. -| `STATE_CLOSED` | The cover has reach the closed position. - - -### Supported Features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Constant | Description | -|----------|--------------------------------------| -| `SUPPORT_OPEN` | The cover supports being opened. -| `SUPPORT_CLOSE` | The cover supports being closed. -| `SUPPORT_SET_POSITION` | The cover supports moving to a specific position between opened and closed. -| `SUPPORT_STOP` | The cover supports stopping the current action (open, close, set position) -| `SUPPORT_OPEN_TILT` | The cover supports being tilting open. -| `SUPPORT_CLOSE_TILT` | The cover supports being tilting closed. -| `SUPPORT_SET_TILT_POSITION` | The cover supports moving to a specific tilt position between opened and closed. -| `SUPPORT_STOP_TILT` | The cover supports stopping the current tilt action (open, close, set position) - -## Methods - -### Open cover - -Only implement this method if the flag `SUPPORT_OPEN` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover(self, **kwargs): - """Open the cover.""" - - async def async_open_cover(self, **kwargs): - """Open the cover.""" -``` - -### Close cover - -Only implement this method if the flag `SUPPORT_CLOSE` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover(self, **kwargs): - """Close cover.""" - - async def async_close_cover(self, **kwargs): - """Close cover.""" -``` - -### Set cover position - -Only implement this method if the flag `SUPPORT_SET_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" - - async def async_set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" -``` - -### Stop cover - -Only implement this method if the flag `SUPPORT_STOP` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover(self, **kwargs): - """Stop the cover.""" -``` - -### Open cover tilt - -Only implement this method if the flag `SUPPORT_OPEN_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" - - async def async_open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" -``` - -### Close cover tilt - -Only implement this method if the flag `SUPPORT_CLOSE_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" - - async def async_close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" -``` - -### Set cover tilt position - -Only implement this method if the flag `SUPPORT_SET_TILT_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" - - async def async_set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" -``` - -### Stop cover tilt - -Only implement this method if the flag `SUPPORT_STOP_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover_tilt(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover_tilt(self, **kwargs): - """Stop the cover.""" -``` diff --git a/website/versioned_docs/version-0.105.0/entity_index.md b/website/versioned_docs/version-0.105.0/entity_index.md deleted file mode 100644 index d43bca12..00000000 --- a/website/versioned_docs/version-0.105.0/entity_index.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Entity -sidebar_label: Introduction -id: version-0.105.0-entity_index -original_id: entity_index ---- - -Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating. - -Below is an example switch entity that keeps track of their state in memory. - -```python -from homeassistant.components.switch import SwitchDevice - - -class MySwitch(SwitchDevice): - def __init__(self): - self._is_on = False - - @property - def name(self): - """Name of the device.""" - return "My Switch" - - @property - def is_on(self): - """If the switch is currently on or off.""" - return self._is_on - - def turn_on(self, **kwargs): - """Turn the switch on.""" - self._is_on = True - - def turn_off(self, **kwargs): - """Turn the switch off.""" - self._is_on = False -``` - -That's all there is to it to build a switch entity! Continue reading to learn more or check out the [video tutorial](https://youtu.be/Cfasc9EgbMU?t=737). - -## Updating the entity - -An entity represents a device. There are various strategies to keep your entity in sync with the state of the device, the most popular one being polling. - -### Polling - -With polling, Home Assistant will ask the entity from time to time (depending on the update interval of the component) to fetch the latest state. Home Assistant will poll an entity when the `should_poll` property returns `True` (the default value). You can either implement your update logic using `update()` or the async method `async_update()`. This method should fetch the latest state from the device and store it in an instance variable for the properties to return it. - -### Subscribing to updates - -When you subscribe to updates, your code is responsible for letting Home Assistant know that an update is available. Make sure you have the `should_poll` property return `False`. - -Whenever you receive new state from your subscription, you can tell Home Assistant that an update is available by calling `schedule_update_ha_state()` or async callback `async_schedule_update_ha_state()`. Pass in the boolean `True` to the method if you want Home Assistant to call your update method before writing the update to Home Assistant. - -## Generic properties - -The entity base class has a few properties that are common among all entities in Home Assistant. These can be added to any entity regardless of the type. All these properties are optional and don't need to be implemented. - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ----------------------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -| assumed_state | boolean | `False` | Return `True` if the state is based on our assumption instead of reading it from the device. | -| available | boolean | `True` | Indicate if Home Assistant is able to read the state and control the underlying device. | -| device_class | string | `None` | Extra classification of what the device is. Each domain specifies their own. Device classes can come with extra requirements for unit of measurement and supported features. | -| device_state_attributes | dict | `None` | Extra information to store in the state machine. It needs to be information that further explains the state, it should not be static information like firmware version. See [below](entity_index.md#standard-attributes) for details of standard attributes. | -| entity_picture | URL | `None` | Url of a picture to show for the entity. | -| name | string | `None` | Name of the entity | -| should_poll | boolean | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](#methods). | -| unique_id | string | `None` | A unique identifier for this entity. Needs to be unique within a platform (ie `light.hue`). Should not be configurable by the user or be changeable. [Learn more.](entity_registry_index.md#unique-id-requirements) | - -## Advanced properties - -The following properties are also available on entities. However, they are for advanced use only and should be used with caution. - -| Name | Type | Default | Description | -| ------------------------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| force_update | boolean | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine. | -| hidden | boolean | `False` | Indicate if the entity should not be shown on the frontend. Deprecated. Will be removed in 0.107.0 | -| icon | icon | `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all devices. | -| entity_registry_enabled_default | boolean | `True` | Indicate if the entity should be enabled or disabled when it is first added to the entity registry. | - -## System properties - -The following properties are used and controlled by Home Assistant, and should not be overridden by integrations. - -| Name | Type | Default | Description | -| ------- | ------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| enabled | boolean | `True` | Indicate if entity is enabled in the entity registry. It also returns `True` if the platform doesn't support the entity registry. Disabled entities will not be added to Home Assistant. | - -## Standard attributes - -The following `device_state_attributes` are considered standard and should follow the convention below. The constant should be imported from `homeassistant/const.py`. - -| Name | Type | Unit | Constant | Description | -| ---------------- | ------- | ---- | ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | -| battery_charging | boolean | N/A | `ATTR_BATTERY_CHARGING` | Battery charging status of the entity, shown as a boolean `true` or `false`. If charging is not supported, then this attribute should not be created. | -| battery_level | integer | % | `ATTR_BATTERY_LEVEL` | Battery level of the entity, shown as an integer percentage between 0-100. | - -## Lifecycle hooks - -Use these lifecycle hooks to execute code when certain events happen to the entity. All lifecycle hooks are async methods. - -### `async_added_to_hass()` - -Called when an entity has their entity_id and hass object assigned, before it is written to the state machine for the first time. Example uses: restore the state, subscribe to updates or set callback/dispatch function/listener. - -### `async_will_remove_from_hass()` - -Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates. - -## Changing the entity model - -If you want to add a new feature to an entity or any of its subtypes (light, switch, etc), you will need to propose it first in our [architecture repo](https://github.com/home-assistant/architecture/issues). Only additions will be considered that are common features among various vendors. diff --git a/website/versioned_docs/version-0.105.0/entity_lock.md b/website/versioned_docs/version-0.105.0/entity_lock.md deleted file mode 100644 index 7dc60c7c..00000000 --- a/website/versioned_docs/version-0.105.0/entity_lock.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: Lock Entity -sidebar_label: Lock -id: version-0.105.0-entity_lock -original_id: entity_lock ---- - -A lock entity is a device which is able to lock and unlock. Locking and unlocking can optionally be secured with a user code. Some locks also allow for opening of latches, this may also be secured with a user code. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| changed_by | string | None | Describes what the last change was triggered by. -| code_format | string | None | Regex for code format or None if no code is required. -| is_locked | bool | None | Indication of whether the lock is currently locked. Used to determine `state`. - -### Supported Features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Constant | Description | -|----------|--------------------------------------| -| `SUPPORT_OPEN` | This lock supports opening the door latch. - -## Methods - -### Lock - -```python -class MyLock(LockDevice): - - def lock(self, **kwargs): - """Lock all or specified locks. A code to lock the lock with may optionally be specified.""" - - async def async_lock(self, **kwargs): - """Lock all or specified locks. A code to lock the lock with may optionally be specified.""" -``` - -### Unlock - -```python -class MyLock(LockDevice): - - def unlock(self, **kwargs): - """Unlock all or specified locks. A code to unlock the lock with may optionally be specified.""" - - async def async_unlock(self, **kwargs): - """Unlock all or specified locks. A code to unlock the lock with may optionally be specified.""" -``` - -### Open - -Only implement this method if the flag `SUPPORT_OPEN` is set. - -```python -class MyLock(LockDevice): - - def open(self, **kwargs): - """Open (unlatch) all or specified locks. A code to open the lock with may optionally be specified.""" - - async def async_open(self, **kwargs): - """Open (unlatch) all or specified locks. A code to open the lock with may optionally be specified.""" -``` diff --git a/website/versioned_docs/version-0.105.0/entity_registry_disabled_by.md b/website/versioned_docs/version-0.105.0/entity_registry_disabled_by.md deleted file mode 100644 index f4eb0def..00000000 --- a/website/versioned_docs/version-0.105.0/entity_registry_disabled_by.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Entity Registry and disabling entities -sidebar_label: Disabling entities -id: version-0.105.0-entity_registry_disabled_by -original_id: entity_registry_disabled_by ---- - -The entity registry tracks all entities with unique IDs. For each entity, the registry keeps track of options that impact how the entity interacts with the core. One of these options is `disabled_by`. - -When `disabled_by` is set to a string value, the entity will not be added to Home Assistant when the integration passes it to `async_add_entities`. - -## Integration Architecture - -Integrations will need to make sure that they work correctly when their entities get disabled. If your integration is keeping references to the created entity objects, it should register those references only inside the entity's lifecycle method `async_added_to_hass`. This lifecycle method is only called if the entity is actually added to Home Assistant (and so it's not disabled). - -Entity disabling works with entities provided via a config entry or via an entry in configuration.yaml. If your integration is set up via a config entry and supports [unloading](config_entries_index.md#unloading-entries), Home Assistant will be able to reload your integration after entities have been enabled/disabled to apply the changes without a restart. - -## Users editing the entity registry - -One way an entity can be disabled is by the user editing the entity registry via the UI. In this case, the `disabled_by` value will be set to `user`. This will only work with entities that are already registered. - -## Integrations setting default value of disabled_by for new entity registry entries - -As an integration you can control if your entity is enabled when it is first registered. This is controlled by the `entity_registry_enabled_default` property. It defaults to `True`, which means the entity will be enabled. - -If the property returns `False`, the `disabled_by` value of the newly registered entity will be set to `integration`. - -## Config entry system options setting default value of disabled_by for new entity registry entries - -The user can also control how new entities that are related to a config entry are received by setting the system option `disable_new_entities` of a config entry to `True`. This can be done via the UI. - -If an entity is getting registered and this system option is set to `True`, the `disabled_by` property will be initialized as `config_entry`. - -If `disable_new_entities` is set to `True` and `entity_registry_enabled_default` returns `False`, the `disabled_by` value will be set to `integration`. - -## Integrations offering options to control disabled_by - -Some integrations will want to offer options to the user to control which entities are being added to Home Assistant. For example, the Unifi integration offers options to enable/disable wireless and wired clients. - -Integrations can offer options to users either via [configuration.yaml](configuration_yaml_index) or using an [Options Flow](config_entries_options_flow_handler.md). - -If this option is offered by integrations, you should not leverage the disabled_by property in the entity registry. Instead, if entities are disabled via a config options flow, remove them from the device and entity registry. diff --git a/website/versioned_docs/version-0.105.0/external_api_rest.md b/website/versioned_docs/version-0.105.0/external_api_rest.md deleted file mode 100644 index e726d1d7..00000000 --- a/website/versioned_docs/version-0.105.0/external_api_rest.md +++ /dev/null @@ -1,554 +0,0 @@ ---- -title: REST API -id: version-0.105.0-external_api_rest -original_id: external_api_rest ---- - -Home Assistant provides a RESTful API on the same port as the web frontend. (default port is port 8123). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -* http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -* http://IP_ADDRESS:8123/api/ is a RESTful API. - -The API accepts and returns only JSON encoded objects. - -All API calls have to be accompanied by the header `Authorization: Bearer ABCDEFGH`, where `ABCDEFGH` is replaced by your token. You can obtain a token ("Long-Lived Access Token") by logging into the frontend using a web browser, and going to [your profile](https://www.home-assistant.io/docs/authentication/#your-account-profile) `http://IP_ADDRESS:8123/profile`. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```shell -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. - -```python -from requests import get - -url = "http://localhost:8123/ENDPOINT" -headers = { - "Authorization": "Bearer ABCDEFGH", - "content-type": "application/json", -} - -response = get(url, headers=headers) -print(response.text) -``` -Another option is to use the Restful Command component https://www.home-assistant.io/components/rest_command/ in a Home Assistant automation or script. - -```yaml -turn_light_on: - url: http://localhost:8123/api/states/light.study_light - method: POST - headers: - authorization: 'Bearer ABCDEFGH' - content-type: 'application/json' - payload: '{"state":"on"}' -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on one or more entities - comma separated. -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```shell -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates a state. You can create any state that you want, it does not have to be backed by an entity in Home Assistant. - -> :info: NOTE: This endpoint sets the representation of a device within Home Asistant and will not communicate with the actual device. To communicate with the device, use the [POST /api/services/<domain>/<service>](#post-apiservicesltdomainltservice) endpoint. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```shell -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```shell -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```shell -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```shell -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now() }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/config/core/check_config - -Trigger a check of `configuration.yaml`. No additional data needs to be passed in with this request. - -If the check is successful, the following will be returned: - -```javascript -{ - "errors": null, - "result": "valid" -} -``` - -If the check fails, the errors attribute in the object will list what caused the check to fail. For example: - -```javascript -{ - "errors": "Integration not found: frontend:", - "result": "invalid" -} -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance.
- -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` diff --git a/website/versioned_docs/version-0.105.0/frontend_data.md b/website/versioned_docs/version-0.105.0/frontend_data.md deleted file mode 100644 index 9aabec59..00000000 --- a/website/versioned_docs/version-0.105.0/frontend_data.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -title: Frontend data -sidebar_label: Data -id: version-0.105.0-frontend_data -original_id: frontend_data ---- - -The frontend passes a single `hass` object around. This object contains the latest state and allows you to send commands back to the server. - -Whenever a state changes, a new version of the objects that changed are created. So you can easily see if something has changed by doing a strict equality check: - -```js -const changed = newVal !== oldVal; -``` - -## Data - -### `hass.states` - -An object containing the states of all entities in Home Assistant. The key is the entity_id, the value is the state object. - -```json -{ - "sun.sun": { - "entity_id": "sun.sun", - "state": "above_horizon", - "attributes": { - "next_dawn": "2018-08-18T05:39:19+00:00", - "next_dusk": "2018-08-17T18:28:52+00:00", - "next_midnight": "2018-08-18T00:03:51+00:00", - "next_noon": "2018-08-18T12:03:58+00:00", - "next_rising": "2018-08-18T06:00:33+00:00", - "next_setting": "2018-08-17T18:07:37+00:00", - "elevation": 60.74, - "azimuth": 297.69, - "friendly_name": "Sun" - }, - "last_changed": "2018-08-17T13:46:59.083836+00:00", - "last_updated": "2018-08-17T13:49:30.378101+00:00", - "context": { - "id": "74c2b3b429c844f18e59669e4b41ec6f", - "user_id": null - }, - }, - "light.ceiling_lights": { - "entity_id": "light.ceiling_lights", - "state": "on", - "attributes": { - "min_mireds": 153, - "max_mireds": 500, - "brightness": 180, - "color_temp": 380, - "hs_color": [ - 56, - 86 - ], - "rgb_color": [ - 255, - 240, - 35 - ], - "xy_color": [ - 0.459, - 0.496 - ], - "white_value": 200, - "friendly_name": "Ceiling Lights", - "supported_features": 151 - }, - "last_changed": "2018-08-17T13:46:59.129248+00:00", - "last_updated": "2018-08-17T13:46:59.129248+00:00", - "context": { - "id": "2c6bbbbb66a84a9dae097b6ed6c93383", - "user_id": null - }, - } -} -``` - -### `hass.user` - -The logged in user. - -```json -{ - "id": "758186e6a1854ee2896efbd593cb542c", - "name": "Paulus", - "is_owner": true, - "is_admin": true, - "credentials": [ - { - "auth_provider_type": "homeassistant", - "auth_provider_id": null - } - ] -} -``` - -## Methods - -All methods starting with `call` are async methods. This means that they will return a `Promise` that will resolve with the result of the call. - -### `hass.callService(domain, service, data)` - -Call a service on the backend. - -```js -hass.callService('light', 'turn_on', { - entity_id: 'light.kitchen' -}); -``` - -### `hass.callWS(message)` - -Call a WebSocket command on the backend. - -```js -this.hass.callWS({ - type: 'config/auth/create', - name: 'Paulus', -}).then(userResponse => - console.log("Created user", userResponse.user.id)); -``` - -### `hass.callApi(method, path, data)` - -Call an API on the Home Assistant server. For example, if you want to fetch all Hass.io snapshots by issuing a GET request to `/api/hassio/snapshots`: - -```js -hass.callApi('get', 'hassio/snapshots') - .then(snapshots => console.log('Received snapshots!', snapshots)); -``` - -If you need to pass in data, pass a third argument: - -```js -hass.callApi('delete', 'notify.html5', { subscription: 'abcdefgh' }); -``` - -_We're moving away from API calls and are migrating everything to `hass.callWS(message)` calls._ diff --git a/website/versioned_docs/version-0.105.0/hassio_addon_config.md b/website/versioned_docs/version-0.105.0/hassio_addon_config.md deleted file mode 100644 index 5ced5a01..00000000 --- a/website/versioned_docs/version-0.105.0/hassio_addon_config.md +++ /dev/null @@ -1,237 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.105.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - apparmor.txt - build.json - CHANGELOG.md - config.json - DOC.md - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -All our Images have also [bashio][bashio] installed. It contains a set of commonly used operations and can be used to be included in add-ons to reduce code duplication across add-ons and therefore making it easier to develop and maintain add-ons. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use bashio or `jq` inside your shell script to parse this data. - -```shell -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -[bashio]: https://github.com/hassio-addons/bashio - -## Add-on Docker file - -All add-ons are based on latest Alpine Linux. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -```dockerfile -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | yes | List of supported arch: `armhf`, `armv7`, `aarch64`, `amd64`, `i386`. -| machine | list | no | Default it support any machine type. You can select that this add-on run only on specific machines. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | string | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. If host-port is `null`, the mapping is disabled. -| ports_description | dict | no | Network ports description mapping. Format is `"container-port/type": "description of this port"`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| udev | bool | no | Default False. Set this True, if your container runs a udev process of its own. -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| homeassistant | string | no | Pin a minimum required Home Assistant version for such Add-on. Value is a version string like `0.91.2`. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| video | bool | no | Boolean. Mark this add-on touse internal an video system. All available devices will be mapped into addon. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| kernel_modules | bool | no | Map host kernel modules and config into add-on (readonly). -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| auth_api | bool | no | Allow access to Home Assistent user backend. -| ingress | bool | no | Enable the ingress feature for the Add-on -| ingress_port | integer | no | Default `8099`. For Add-ons they run on host network, you can use `0` and read the port later on API. -| ingress_entry | string | no | Modify the URL entry point from `/`. -| panel_icon | string | no | Default: mdi:puzzle. MDI icon for the menu panel integration. -| panel_title | string | no | Default add-on name, but can Modify with this options. -| panel_admin | bool | no | Default True. Make menu entry only available with admin privileged. -| snapshot_exclude | list | no | List of file/path with glob support they are excluded from snapshots. -| advanced | bool | no | Default False. Make addon visible on simle mode or not. -| stage | string | no | Default `stable`. Flag add-on with follow attribute: `stable`, `experimental`, `deprecated` - - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str / str(min,) / str(,max) / str(min,max) -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- password -- port -- match(REGEX) -- list(val1|val2|...) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. - -We provide a set of [Base-Images][hassio-base] which should cover a lot of needs. If you don't want use the Alpine based version or need a specific Image tag, feel free to pin this requirements for you build with `build_from` option. - -[hassio-base]: https://github.com/home-assistant/hassio-base diff --git a/website/versioned_docs/version-0.105.0/hassio_addon_presentation.md b/website/versioned_docs/version-0.105.0/hassio_addon_presentation.md deleted file mode 100644 index 08e70be1..00000000 --- a/website/versioned_docs/version-0.105.0/hassio_addon_presentation.md +++ /dev/null @@ -1,66 +0,0 @@ ---- -title: Presenting your addon -id: version-0.105.0-hassio_addon_presentation -original_id: hassio_addon_presentation ---- - -If you decide to share your add-on to the public, paying attention to details is recommended. Of course, your add-on should have a proper name and description, but Hass.io also gives you some other tools to present your add-on even nicer. - -## Adding intro - -This shows in add-on store and give the user a short instruction what the addon can. - -This file containing the intro is usually referred to as the "README", which is generally published as the `README.md` file. - -## Adding documentation - -Good documentation helps the consumer of your add-on to understand its usage, explains configuration options, points users in the right direction in the case they have questions or issues, and contains the license under which the add-on was published. - -This file containing the documentation is usually referred to as the "DOC", which is generally published as the `DOC.md` file. - -## Add-on icon & logo - -A picture is worth a thousand words. Therefore, your add-on can be improved by adding a proper image icon and logo. Those images are used when showing your add-on in the Home Assistant Hass.io panel and which will significantly improve the visual representation of your add-on. - -Requirements for the logo of your add-on: - -- The logo must be in the Portable Network Graphics format (`.png`). -- The filename must be `logo.png`. -- It is recommended to keep the logo size around 250x100px. You may choose to use a different size or aspect ratio as you seem fit for your add-on. - -Requirements for the icon of your add-on: - -- The icon must be in the Portable Network Graphics format (`.png`). -- The filename must be `icon.png`. -- The aspect ratio of the icon must be 1x1 (square). -- It is recommended to use an icon size of 128x128px. - -## Keeping a changelog - -It is likely you are going to release newer versions of your add-on in the future. In case that happens, the users of your add-on would see an upgrade notice and probably want to know what changes were made in the latest version. - -A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of your add-on and is generally published as the `CHANGELOG.md` file. - -If you are in need of a guide on keeping a changelog, we would recommend checking the [keep a changelog](http://keepachangelog.com) website. They have developed a standard that is used by many opensource projects around the world. - -In future versions of Hass.io, the `CHANGELOG.md` file will be displayed in the Home Assistant frontend. - -## AppArmor - -You can use own security profile for you Add-on with AppArmor. Default it is enabled and use the Docker default profile. Put `apparmor.txt` file into your Add-on folder and it will load this file as primary profile. Use the config options to set the name of that profile. - -## Ingress - -Ingress allow users to access the add-on web interface via the Home Assistant UI. Authentication is handled by Home Assistant, so neither the user nor the add-on developer will need to care about the security or port forwarding. Users love this feature, however it is not every time simple to implement for the add-on developer. - -To add Ingress support, follow the following steps: -- The add-on will need to provide the web interface on port `8099`. Make sure that the add-on accepts only connections from `172.30.32.2` on that port and that the connections are treated as authenticated. -- Update add-on configuration and set `ingress: true`. Here it is also possible to configure the Ingress port (default 8099). -- If you need to configure the application inside your add-on with the right path and port, query the add-on info API endpoint. -- If the application doesn't support relative paths or you can't set a base url, you can use nginx filter to replace the URL with correct path. - -Ingress API gateway supports the following: - - * HTTP/1.x - * Streaming content - * Websockets diff --git a/website/versioned_docs/version-0.105.0/integration_fetching_data.md b/website/versioned_docs/version-0.105.0/integration_fetching_data.md deleted file mode 100644 index 7f388774..00000000 --- a/website/versioned_docs/version-0.105.0/integration_fetching_data.md +++ /dev/null @@ -1,154 +0,0 @@ ---- -title: Fetching Data -id: version-0.105.0-integration_fetching_data -original_id: integration_fetching_data ---- - -Your integration will need to fetch data from an API to be able to provide this to Home Assistant. This API can be available over the web (local or cloud), sockets, serial ports exposed via USB sticks, etc. - -# Push vs Poll - -APIs come in many different shapes and forms but at its core they fall in two categories: push and poll. - -With push, we subscribe to an API and we get notified by the API when new data is available. It pushes the changes to us. Push APIs are great because they consume less resources. When a change happens, we can get notified of a change and don't have to re-fetch all the data and find changes. Because entities can be disabled, you should make sure that your entity subscribes inside the `async_added_to_hass` callback and unsubscribes inside `async_will_remove_from_hass`. - -With polling, we will fetch the latest data from the API at a specified interval. Your integration will then supply this data to its entity, which is written to Home Assistant. - -Because polling is so common, Home Assistant by default assumes that your entity is based on polling. If this is not the case, return `False` from the `Entity.should_poll` property. When you disable polling, your integration will be responsible for calling one of the methods to indicate to Home Assistant that it's time to write the entity state to Home Assistant: - -- If you are executing from within an async function and don't need your entity update method called, call `Entity.async_write_ha_state()`. This is an async callback that will write the state to the state machine within yielding to the event loop. -- `Entity.schedule_update_ha_state(force_refresh=False)`/`Entity.async_schedule_update_ha_state(force_refresh=False)` will schedule an update of the entity. If `force_refresh` is set to `True`, Home Assistant will call your entities update method (`update()`/`async_update()`) prior to writing the state. - -# Polling API endpoints - -We're going to explain a few different API types here and the best way to integrate them in Home Assistant. Note that some integrations will encounter a combination of the ones below. - -## Coordinated, single API poll for data for all entities - -This API will have a single method to fetch data for all the entities that you have in Home Assistant. In this case we will want to have a single periodical poll on this endpoint, and then let entities know as soon as new data is available for them. - -Home Assistant provides a DataUpdateCoordinator class to help you manage this as efficiently as possible. - -```python -import logging - -from homeassistant.helpers import debounce, entity -from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed -from .const import DOMAIN - -_LOGGER = logging.getLogger(__name__) - -async def async_setup_entry(hass, entry, async_add_entities): - # assuming API object stored here by __init__.py - api = hass.data[DOMAIN][entry.entry_id] - - async def async_update_data(): - """Fetch data from API endpoint. - - This is the place to pre-process the data to lookup tables - so entities can quickly look up their data. - """ - try: - return await api.fetch_data() - except ApiError: - raise UpdateFailed - - coordinator = DataUpdateCoordinator( - hass, - _LOGGER, - # Name of the data. For logging purposes. - name="sensor", - update_method=async_update_data, - # Polling interval. Will only be polled if there are subscribers. - update_interval=timedelta(seconds=30), - ) - - # Fetch initial data so we have data when entities subscribe - await coordinator.async_refresh() - - async_add_entities(MyEntity(coordinator, idx) for idx, ent - in enumerate(coordinator.data)) - - -class MyEntity(entity.Entity): - - def __init__(self, coordinator, idx): - self.coordinator = coordinator - self.idx = idx - - @property - def is_on(self): - """Return entity state. - - Example to show how we fetch data from coordinator. - """ - self.coordinator.data[self.idx]['state'] - - @property - def should_poll(self): - """No need to poll. Coordinator notifies entity of updates.""" - return False - - @property - def available(self): - """Return if entity is available.""" - return not self.coordinator.failed_last_update - - async def async_added_to_hass(self): - """When entity is added to hass.""" - self.coordinator.async_add_listener( - self.async_write_ha_state - ) - - async def async_will_remove_from_hass(self): - """When entity will be removed from hass.""" - self.coordinator.async_remove_listener( - self.async_write_ha_state - ) - - async def async_turn_on(self, **kwargs): - """Turn the light on. - - Example method how to request data updates. - """ - # Do the turning on. - # ... - - # Update the data - await self.coordinator.async_request_refresh() - - async def async_update(self): - """Update the entity. - - Only used by the generic entity update service. - """ - await self.coordinator.async_request_refresh() -``` - -## Separate polling for each individual entity - -Some APIs will offer an endpoint per device. It sometimes won't be possible to map a device from your API to a single entity. If you create multiple entities from a single API device endpoint, please see the preivous section. - -If you can map exactly one device endpoint to a single entity, you can fetch the data for this entity inside the `update()`/`async_update()` methods. Make sure polling is set to `True` and Home Assistant will call this method regularly. - -If your entities need to fetch data before being written to Home Assistant for the first time, pass `True` to the `add_entities` method: `add_entities([MyEntity()], True)`. - -You can control the polling interval for your integration by defining a `SCAN_INTERVAL` constant in your platform. Careful with setting this too low. It will take up resources in Home Assistant, can overwelm the device hosting the API or can get you blocked from cloud APIs. - -```python -from datetime import timedelta - -SCAN_INTERVAL = timedelta(seconds=5) -``` - -# Request Parallelism - -> This is an advanced topic. - -Home Assistant has built-in logic to make sure that integrations do not hammer APIs and consume all available resources in Home Assistant. This logic is built around limiting the number of parallel requests. This logic is automatically used during service calls and entity updates. - -Home Assistant controls the number of parallel updates (calls to `update()`) by maintaining a [semaphore](https://docs.python.org/3/library/asyncio-sync.html#asyncio.Semaphore) per integration. For example, if the semaphore allows 1 parallel connection, updates and service calls will wait if one is in progress. If the value is 0, the integration is itself responsible for limiting the number of parallel requests if necessary. - -The default value for parallel requests for a platform is decided based on the first entity that is added to Home Assistant. It's 0 if the entity defines the `async_update` method, else it's 1. (this is a legacy decision) - -Platforms can override the default by defining the `PARALLEL_UPDATES` constant in their platform (ie `rflink/light.py`). diff --git a/website/versioned_docs/version-0.105.0/integration_quality_scale_index.md b/website/versioned_docs/version-0.105.0/integration_quality_scale_index.md deleted file mode 100644 index 65512f3a..00000000 --- a/website/versioned_docs/version-0.105.0/integration_quality_scale_index.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Integration Quality Scale -id: version-0.105.0-integration_quality_scale_index -original_id: integration_quality_scale_index ---- - -The Integration Quality Scale scores each integration based on the code quality and user experience. Each level of the quality scale consists of a list of requirements. If an integration matches all requirements, it's considered to have reached that level. - -> Suggestions for changes can be done by creating an issue in the [architecture repo](https://github.com/home-assistant/architecture/issues/). - -# No score - -This integration passes the bare minimum requirements to become part of the index. - -- Satisfy all requirements for [creating components](creating_component_code_review.md) and [creating platforms](creating_platform_code_review.md). -- Configurable via `configuration.yaml` - -# Silver 🥈 - -This integration is able to cope when things go wrong. It will not print any exceptions nor will it fill the log with retry attempts. - -- Connection/configuration is handled via a component. -- Set an appropriate `SCAN_INTERVAL` (if a polling integration) -- Raise `PlatformNotReady` if unable to connect during platform setup (if appropriate) -- Handles expiration of auth credentials. Refresh if possible or print correct error and fail setup. If based on a config entry, should trigger a new config entry flow to re-authorize. -- Handles internet unavailable. Log a warning once when unavailable, log once when reconnected. -- Handles device/service unavailable. Log a warning once when unavailable, log once when reconnected. -- Set `available` property to `False` if appropriate ([docs](entity_index.md#generic-properties)) -- Entities have unique ID (if available) ([docs](entity_registry_index.md#unique-id-requirements)) - -# Gold 🥇 - -This is a solid integration that is able to survive poor conditions and can be configured via the user interface. - -- Configurable via config entries. - - Don't allow configuring already configured device/service (example: no 2 entries for same hub) - - Tests for the config flow - - Discoverable (if available) - - Set unique ID in config flow (if available) -- Entities have device info (if available) ([docs](device_registry_index.md#defining-devices)) -- Tests for fetching data from the integration and controlling it ([docs](development_testing.md)) -- Has a code owner ([docs](creating_integration_manifest.md#code-owners)) -- Entities only subscribe to updates inside `async_added_to_hass` and unsubscribe inside `async_will_remove_from_hass` ([docs](entity_index.md#lifecycle-hooks)) -- Entities have correct device classes where appropriate ([docs](entity_index.md#generic-properties)) -- Supports entities being disabled and leverages `Entity.entity_registry_enabled_default` to disable less popular entities ([docs](entity_index.md#advanced-properties)) -- If the device/service API can remove entities, the integration should make sure to clean up the entity and device registry. - -# Platinum 🏆 - -Best of the best. The integration is completely async, meaning it's super fast. Integrations that reach platinum level will require approval by the code owner for each PR. - -- Set appropriate `PARALLEL_UPDATES` constant -- Support config entry unloading (called when config entry is removed) -- Integration + dependency are async -- Uses aiohttp and allows passing in websession (if making HTTP requests) - -# Internal 🏠 - -Integrations which are part of Home Assistant are not rated but marked as **internal**. diff --git a/website/versioned_docs/version-0.72/architecture_components.md b/website/versioned_docs/version-0.72/architecture_components.md deleted file mode 100644 index 9c8b88a9..00000000 --- a/website/versioned_docs/version-0.72/architecture_components.md +++ /dev/null @@ -1,55 +0,0 @@ ---- -title: Components Architecture -sidebar_label: Components -id: version-0.72-architecture_components -original_id: architecture_components ---- - -Home Assistant can be extended with **components**. Each component is responsible for a specific domain within Home Assistant. Components can listen for or trigger events, offer services, and maintain states. Components are written in Python and can do all the goodness that Python has to offer. Out of the box, Home Assistant offers a bunch of [built-in components](https://www.home-assistant.io/components/). - -Diagram showing interaction between components and the Home Assistant core. - -There are two types of components within Home Assistant: components that interact with an Internet of Things domain, and components that respond to events that happen within Home Assistant. Read on to learn about each type! - -## Components that interact with an Internet-of-Things domain - -These components track devices within a specific domain and consist of a core part and platform-specific logic. These components make their information available via the State Machine and the Event Bus. The components also register services in the Service Registry to expose control of the devices. - -For example, the built-in [`switch` component](https://www.home-assistant.io/components/switch/) is responsible for interaction with different types of switches. A platform provides support for a particular kind or brand of device. For example, a switch could use a WeMo or Orvibo platform and a light component might interact with the Hue or LIFX platform. - -If you want to add support for a new platform, check out the [add new platform section](creating_platform_index.md). - -## Components that respond to events that happen within Home Assistant - -These components provide small pieces of home automation logic or involve services that do common tasks within your house. - -For example, the [`device_sun_light_trigger` component](https://www.home-assistant.io/components/device_sun_light_trigger/) tracks the state of devices and the sun to make sure that the lights are turned on when it gets dark and people are home. The component uses logic like this: - -```text -In the event that device 'Paulus Nexus 5' changes to the 'Home' state: - If the sun has set and the lights are not on: - Turn on the lights -``` - -```text -In the event that the combined state of all tracked devices changes to 'Not Home': - If the lights are on: - Turn off the lights -``` - -```text -In the event of the sun setting: - If the lights are off and the combined state of all tracked device equals 'Home': - Turn on the lights -``` - -## The full picture - -When we put all the different pieces of Home Assistant together, it's a close match for the initial home automation overview sketch. The smart home AI has not been implemented yet, so it's not included in this picture. - -Overview of the full Home Assistant architecture with a couple of loaded components and platforms - -The platform logic for components uses third-party Python libraries to communicate with the devices. Through this, we can leverage some of the best libraries in the Python community. diff --git a/website/versioned_docs/version-0.72/architecture_entities.md b/website/versioned_docs/version-0.72/architecture_entities.md deleted file mode 100644 index 2b07be9c..00000000 --- a/website/versioned_docs/version-0.72/architecture_entities.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Entity Architecture -sidebar_label: Entity -id: version-0.72-architecture_entities -original_id: architecture_entities ---- - -![Architecture overview of Hass.io](/img/en/architecture/entities_architecture.png) - -## Configuration - -Configuration is provided by the [configuration.yaml file](configuration_yaml_index.md) or by a [Config Entry](config_entries_index.md). - -## Component - -Examples of components: `light`, `switch`. - -The component is responsible for defining the Abstract Entity Class and services to control the entities. - -## Entity Component - -The Entity Component is responsible for: - - - Distributing the configuration to the platforms - - Forward config entries and discoveries - - Collect entities for service calls - - Optionally maintain a group of all entities - -## Entity Platform - -The Entity Platform manages all entities for the platform and polls them for updates if necessary. - -When adding entities, the Entity Platform will query the Entity Registry to make sure that the entities to be added have the correct entity IDs. - -## Entity Registry - -The [Entity Registry](entity_registry_index.md) will track entities and allows users to store extra settings for an entity. - -## Platform - -Examples of platforms: `light.hue`, `switch.wemo`. - -Platform uses configuration to query the external device/service and add entities to the entity platform. diff --git a/website/versioned_docs/version-0.72/architecture_hassio.md b/website/versioned_docs/version-0.72/architecture_hassio.md deleted file mode 100644 index d22fd98a..00000000 --- a/website/versioned_docs/version-0.72/architecture_hassio.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Hass.io Architecture -sidebar_label: Hass.io -id: version-0.72-architecture_hassio -original_id: architecture_hassio ---- - -![Architecture overview of Hass.io](/img/en/architecture/hassio.png) - -## Host Control (HC) - -This is a daemon running on the host machine that allows the supervisor to control certain aspects of the host OS: - - - Power cycle (restart, turn off) - - Manage network settings - - Local updates - -## Host - -Our pre-build images are based on [ResinOS]. Any Linux machine can be turned into a Hass.io host by running [the installer][linux]. - -## Supervisor - -The supervisor offers an API to manage the host and running the Docker containers. - -## Configuration panel - -The configuration panel lives inside the supervisor but is accessible via the Home Assistant user interface. The configuration panel allows the user to manage the installation. - -[ResinOS]: https://resinos.io/ -[linux]: https://www.home-assistant.io/hassio/installation/#alternative-install-on-generic-linux-server diff --git a/website/versioned_docs/version-0.72/architecture_index.md b/website/versioned_docs/version-0.72/architecture_index.md deleted file mode 100644 index fdfe6ab8..00000000 --- a/website/versioned_docs/version-0.72/architecture_index.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Architecture -sidebar_label: Introduction -id: version-0.72-architecture_index -original_id: architecture_index ---- - -Before we dive into the Home Assistant architecture, let's get a clear overview of the home automation landscape as a whole. This way, we can show how the different parts of Home Assistant fit into the picture. - -For more information about each part in this overview, check out our blog. Here's the tl;dr version of the blog: - - * Home Control is responsible for collecting information and controlling devices. - * Home Automation triggers commands based on user configurations. - * Smart Home triggers commands based on previous behavior. - -Home Automation landscape - -The Home Assistant core is responsible for Home Control. Home Assistant contains four parts which make this possible: - - * **Event Bus**: facilitates the firing and listening of events -- the beating heart of Home Assistant. - * **State Machine**: keeps track of the states of things and fires a `state_changed` event when a state has been changed. - * **Service Registry**: listens on the event bus for `call_service` events and allows other code to register services. - * **Timer**: sends a `time_changed` event every 1 second on the event bus. - -Overview of the Home Assistant core architecture diff --git a/website/versioned_docs/version-0.72/asyncio_101.md b/website/versioned_docs/version-0.72/asyncio_101.md deleted file mode 100644 index 3e2ecd1e..00000000 --- a/website/versioned_docs/version-0.72/asyncio_101.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Asyncio 101 -id: version-0.72-asyncio_101 -original_id: asyncio_101 ---- - -If you are not familiar yet with asyncio, please watch the below video. It's a great introduction by [Robert Smallshire][rob] in how and why asyncio works the way it does. - -
- -
- -[rob]: https://github.com/rob-smallshire \ No newline at end of file diff --git a/website/versioned_docs/version-0.72/asyncio_categorizing_functions.md b/website/versioned_docs/version-0.72/asyncio_categorizing_functions.md deleted file mode 100644 index 0d898e52..00000000 --- a/website/versioned_docs/version-0.72/asyncio_categorizing_functions.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Categorizing Functions -id: version-0.72-asyncio_categorizing_functions -original_id: asyncio_categorizing_functions ---- - -A piece of work within Home Assistant is represented by a function that will be invoked. It will either run inside our event loop or inside our thread pool, depending on if it is async safe. - -Home Assistant uses the convention that all functions that must be run from within the event loop are prefixed with `async_`. - -## The coroutine function - -Coroutines are special functions based on Python’s generators syntax which allows them to suspend execution while waiting on a result. - -Invoking a coroutine function will return a Generator object back, but will not actually begin execution. This object will execute the task when it is either yielded from (from within another coroutine) or it is scheduled on the event loop. - -To declare a function a coroutine, import the coroutine annotation from the asyncio package and annotate your function. - -```python -async def async_look_my_coroutine(target): - result = await entity.async_turn_on() - if result: - print("hello {}".format(target)) - -hass.loop.create_task(async_look_my_coroutine("world")) -``` - -In this example, we schedule the coroutine by calling `hass.loop.create_task`. This will add the coroutine to the queue of tasks to be run. When the event loop is running `async_look_my_coroutine` it will suspend the task when `yield from entity.async_turn_on()` is called. At that point a new task will be scheduled to execute `entity.async_turn_on()`. When that job has been executed, `async_look_my_coroutine` will resume. - -## The callback function - -This is a normal function that is considered safe to be run from within the event loop. A callback is unable to suspend itself and thus cannot do any I/O or call a coroutine. A callback is capable of scheduling a new task but it will not be able to wait for the results. - -To declare a function as a callback, import the callback annotation from the core package and annotate your function. - -A common use case for a callback in Home Assistant is as a listener for an event or a service call. It can process the incoming information and then schedule the right calls to be made. Example from the automation component. - -```python -from homeassistant.core import callback - -@callback -def async_trigger_service_handler(service_call): - """Handle automation trigger service calls.""" - vars = service_call.data.get(ATTR_VARIABLES) - for entity in component.async_extract_from_service(service_call): - hass.loop.create_task(entity.async_trigger(vars, True)) -``` - -In this example, `entity.async_trigger` is a coroutine function. Invoking the coroutine function will return a coroutine task. The passed in parameters will be used when the task gets executed. - -To execute the task we have to schedule it for execution on the event loop. This is done by calling `hass.loop.create_task`. - -### Why even have callbacks? - -You might wonder, if a coroutine can do everything a callback can do, why even have a callback. The reason is performance and better state consistency of the core API objects. - -When coroutine A waits for coroutine B, it will suspend itself and schedule a new task to run B. This means that the event loop is now running A, B and then A again. If B is a callback, A will never have to suspend itself and thus the event loop is just running A. The consistency implication is that other events queued to run on the event loop continue to wait until callbacks complete, but will be interleaved when yielding to another coroutine. - -## Event loop and thread safe - -These are functions that are safe to run both in a thread and inside the event loop. These functions are usually performing a computation or transform data in memory. Anything that does I/O does not fall under this category. Many standard library functions fall in this category. For example generating the sum of a set of numbers using sum or merging two dictionaries. - -There is no special annotation to mark functions as part of this category and care should be taken when using these functions from inside the event loop. When in doubt, look at their implementation. - -## Other functions - -These are all the functions that did not fit in the previous categories. These functions are either thread-safe or not considered safe to be run within the event loop. These are functions that use sleep, or perform I/O. - -There is no special annotation necessary to be considered part of this category. diff --git a/website/versioned_docs/version-0.72/asyncio_index.md b/website/versioned_docs/version-0.72/asyncio_index.md deleted file mode 100644 index 5bbc5806..00000000 --- a/website/versioned_docs/version-0.72/asyncio_index.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Asynchronous Programming -sidebar_label: Introduction -id: version-0.72-asyncio_index -original_id: asyncio_index ---- - -On September 29, 2016 we released [Home Assistant 0.29][0.29] as part of our bi-weekly release schedule. This release introduced a complete overhaul of the core spearheaded by [Ben Bangert][ben]. - -The old core was set up like a “traditional” threaded application. Each resource that was not thread safe (ie. the state of entities) would be protected by a lock. This caused a lot of waiting and potential inconsistency because a task could now end up waiting halfway through its job until some resource got freed. - -Our new core is based on an Python’s built-in asyncio module. Instead of having all threads have access to the core API objects, access is now limited to a special thread called the event loop. All components will now schedule themselves as a task to be executed by the event loop. This gives us the guarantee that only one task is executed at once, meaning we no longer need any locks. - -The only problem with running everything inside the event loop is when a task is doing blocking I/O, what most third-party Python libraries are doing. For example while requesting new information from a device, the core will stop running until we get a response from the device. To handle this, a task is able to suspend itself until the response is available after which it will be enqueued for the event loop to process the result. - -For a task to be able to suspend itself, all code that it calls has to have this capability added. This means in practice that each device integration will need a full rewrite of the library that offers the integration! As this is not something that can be achieved, ever, a 100% backwards compatible API has been added so that no platform will require updating. - -The backwards compatible API works by scheduling a task from a different thread and blocking that thread until the task has been processed by the event loop. - -[0.29]: https://www.home-assistant.io/blog/2016/09/29/async-sleepiq-emoncms-stocks/ -[ben]: https://github.com/bbangert/ diff --git a/website/versioned_docs/version-0.72/asyncio_working_with_async.md b/website/versioned_docs/version-0.72/asyncio_working_with_async.md deleted file mode 100644 index 72397e3b..00000000 --- a/website/versioned_docs/version-0.72/asyncio_working_with_async.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Working with Async -id: version-0.72-asyncio_working_with_async -original_id: asyncio_working_with_async ---- - -Although we have a backwards compatible API, using the async core directly will be a lot faster. Most core components have already been rewritten to leverage the async core. This includes the EntityComponent helper (foundation of light, switch, etc), scripts, groups and automation. - -## Interacting with the core - -[All methods in the Home Assistant core][dev-docs] are implemented in two flavors: an async version and a version to be called from other threads. The versions for other are merely wrappers that call the async version in a threadsafe manner using [the available async utilities][dev-docs-async]. - -So if you are making calls to the core (the hass object) from within a callback or coroutine, use the methods that start with async_. If you need to call an async_ function that is a coroutine, your task must also be a coroutine. - -## Implementing an async component - -To make a component async, implement an async_setup. - -```python -def setup(hass, config): - # Setup your component outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup(hass, config): - # Setup your component inside of the event loop. -``` - -## Implementing an async platform - -For platforms we support async setup. Instead of setup_platform you need to have a coroutine async_setup_platform. - -```python -setup_platform(hass, config, add_entities, discovery_info=None): - # Setup your platform outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup_platform(hass, config, async_add_entities, - discovery_info=None): - # Setup your platform inside of the event loop -``` - -The only difference with the original parameters is that the `add_entities` function has been replaced by the async friendly callback `async_add_entities`. - -## Implementing an async entity - -You can make your entity async friendly by converting your update method to be async. This requires the dependency of your entities to also be async friendly! - -```python -class MyEntity(Entity): - def update(self): - """Retrieve latest state.""" - self._state = fetch_state() -``` - -Will turn into: - -```python -class MyEntity(Entity): - async def async_update(self): - """Retrieve latest state.""" - self._state = await async_fetch_state() -``` - -Make sure that all properties defined on your entity do not result in I/O being done. All data has to be fetched inside the update method and cached on the entity. This is because these properties are read from within the event loop and thus doing I/O will result in the core of Home Assistant waiting until your I/O is done. - -## Calling async functions from threads - -Sometimes it will happen that you’re in a thread and you want to call a function that is only available as async. Home Assistant includes a few async helper utilities to help with this. - -In the following example, `say_hello` will schedule `async_say_hello` and block till the function has run and get the result back. - -```python -from homeassistant.util.async import run_callback_threadsafe - -def say_hello(hass, target): - return run_callback_threadsafe( - hass.loop, async_say_hello, target).result() - -def async_say_hello(hass, target): - return "Hello {}!".format(target) -``` - -## Dealing with passed in functions - -If your code takes in functions from other code, you will not know which category the function belongs to and how they should be invoked. This usually only occurs if your code supplies an event helper like `mqtt.async_subscribe` or `track_state_change_listener`. - -To help with this, there are two helper methods on the hass object that you can call from inside the event loop: - -#### hass.async_run_job - -Use this method if the function should be called as soon as possible. This will call callbacks immediately, schedule coroutines for execution on the event loop and schedule other functions to be run inside the thread pool. - -| Callback | Call immediately. -| Coroutine | Schedule for execution on the event loop. -| Other functions | Schedule for execution in the thread pool. - -#### hass.async_add_job - -Use this method if the function should be called but not get priority over already scheduled calls. - -| Callback | Schedule for execution on the event loop. -| Coroutine | Schedule for execution on the event loop. -| Other functions | Schedule for execution in the thread pool. - -[dev-docs]: https://dev-docs.home-assistant.io/en/master/api/core.html -[dev-docs-async]: https://dev-docs.home-assistant.io/en/dev/api/util.html#module-homeassistant.util.async diff --git a/website/versioned_docs/version-0.72/auth_api.md b/website/versioned_docs/version-0.72/auth_api.md deleted file mode 100644 index 7d00c354..00000000 --- a/website/versioned_docs/version-0.72/auth_api.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Authentication API -sidebar_label: API -id: version-0.72-auth_api -original_id: auth_api ---- - -> This is experimental. It is not persisted and is not yet intended for production. - -This page will describe the steps required to fetch an access token for a user and how to refresh it. We follow the OAuth 2 specification. - -## Requirements - -A client needs to be created inside Home Assistant before a client can request users to authorize it or fetch a new access token. The only way currently to create a client is programmatically: - -```python -client = await hass.auth.async_create_client( - 'Example client', - redirect_uris=['http://www.example.com/hass_callback'], - no_secret=True, -) -print(client.id) -``` - -## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) - - - The authorize url should contain `client_id`, `redirect_uri` and, if available, `client_secret` as query parameters. Example: `http://your-instance.com/auth/authorize?client_id=ABCDE&client_secret=QWERTY&redirect_uri=https%3A%2F%2Fexample.com%2Fhass_callback` - - The user will navigate to this link, log into Home Assistant and authorize the client. - - Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code as part of the query parameters. Example: https://example.com/hass_callback?code=12345 - - This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section). - - As specified in the OAuth 2 specification, it is possible to pass an optional state string to the authorize url using the `state` query parameter. This string will be added as query parameter to the redirect url. - -## Token - -The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. - -All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`. - -### Authorization code - -Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is: - -``` -grant_type=authorization_code&code=12345 -``` - -The return response will be an access and refresh token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "refresh_token": "IJKLMNOPQRST", - "token_type": "Bearer" -} -``` - -### Refresh token - -Use the grant type `refresh_token` to retrieve an access token using a refresh token. The request body is: - -``` -grant_type=refresh_token&refresh_token=QWERTY -``` - -The return response will be an access token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "token_type": "Bearer" -} -``` - -## Making authenticated requests - -Once you have an access token, you can make authenticated requests to the Home Assistant APIs. - -For the websocket connection, pass the access token in the [authentication message](http://localhost:3000/docs/en/external_api_websocket.html#authentication-phase). - -For HTTP requests, pass the token type and access token as the authorization header: - -``` -Authorization: Bearer ABCDEFGH -``` - -If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and the client should ask the user to authorize again. diff --git a/website/versioned_docs/version-0.72/auth_auth_provider.md b/website/versioned_docs/version-0.72/auth_auth_provider.md deleted file mode 100644 index 9704c690..00000000 --- a/website/versioned_docs/version-0.72/auth_auth_provider.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Authentication Providers -id: version-0.72-auth_auth_provider -original_id: auth_auth_provider ---- - -Authentication providers confirm the identity of users. The user proofs their identity by going through the login flow for an auth provider. The auth provider defines the login flow and can ask the user all information this needs. This will commonly be username and password but could also include a 2FA token or other challenges. - -Once an authentication provider has confirmed the identity of a user, it will pass that on to Home Assistant in the form of a Credentials object. - -## Defining an auth provider - -> We currently only support built-in auth providers. Support for custom auth providers might arrive in the future. - -Auth providers are defined in `homeassistant/auth_providers/.py`. The auth provider module will need to provide an implementation of the `AuthProvider` class and contain a credential flow. This flow is what asks user for information and validates it. - -For an example of a fully implemented auth provider, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth_providers/insecure_example.py). - -Auth providers can extend the following methods. - -| method | Required | Description -| ------ | -------- | ----------- -| async def async_credential_flow(self) | Yes | Return an instance of the credential flow for a user to identify itself. -| async def async_get_or_create_credentials(self, flow_result) | Yes | Given the result of a credential flow, return a credentials object. This can either be an existing one or a new one. -| async def async_initialize(self) | No | Callback callled once before interacting with the auth provider for the first time. -| async def async_user_meta_for_credentials(credentials) | No | Callback called Home Assistant is going to create a user from a Credentials object. Can be used to populate extra fields for the user. diff --git a/website/versioned_docs/version-0.72/auth_index.md b/website/versioned_docs/version-0.72/auth_index.md deleted file mode 100644 index fc7300a3..00000000 --- a/website/versioned_docs/version-0.72/auth_index.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Authentication -sidebar_label: Introduction -id: version-0.72-auth_index -original_id: auth_index ---- - -> This is an experimental and unfinished API introduced in Home Assistant 0.69 and later. This is not enabled by default, it's not persisted to disk and should not be used in production. - -Home Assistant has a built-in authentication system allowing different users to interact with Home Assistant. The authentication system consist of various parts. - -![Overview of how the different parts interact](/img/en/auth/architecture.png) - -## Authentication providers - -An authentication provider is used for users to authenticate themselves. It's up to the authentication provider to choose the method of authentication and the backend to use. By default we enable the built-in Home Assistant authentication provider which stores the users securely inside your configuration directory. - -The authentication providers that Home Assistant will use are specified inside `configuration.yaml`. It is possible to have multiple instances of the same authentication provider active. In that case, each will be identified by a unique identifier. Authentication providers of the same type will not share credentials. - -## Credentials - -Credentials store the authentication of a user with a specific authentication provider. It is produced when a user successfully authenticates. It will allow the system to find the user in our system. If the user does not exist, a new user will be created. This user will not be activated but will require approval by the owner. - -It is possible for a user to have multiple credentials linked to it. However, it can only have a single credential per specific authentication provider. - -## Users - -Each person is a user in the system. To log in as a specific user, authenticate with any of the authentication providers that are linked to this user. When a user logs in, it will get a refresh and an access token to make requests to Home Assistant. - -### Owner - -The first user to log in to Home Assistant will be marked as the owner. This user is able to manage users. - -## Clients - -Clients are applications that users use to access the Home Assistant API. Each client has a client identifier, a redirect uri and an optional client secret. The redirect uri is used to redirect the user after it has successfully authorized. - -## Access and refresh tokens - -The client will be provided with an authorization code when a user successfully authorizes with Home Assistant. This code can be used to retrieve an access and a refresh token. The access token will have a limited lifetime while refresh tokens will remain valid until a user deletes it. - -The access token is used to access the Home Assistant APIs. The refresh token is used to retrieve a new valid access token. \ No newline at end of file diff --git a/website/versioned_docs/version-0.72/config_entries_config_flow_handler.md b/website/versioned_docs/version-0.72/config_entries_config_flow_handler.md deleted file mode 100644 index 72118c9b..00000000 --- a/website/versioned_docs/version-0.72/config_entries_config_flow_handler.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Config Flow Handlers -id: version-0.72-config_entries_config_flow_handler -original_id: config_entries_config_flow_handler ---- - -Config Entries uses the [Data Flow Entry framework](data_entry_flow_index.md) to allow users to create entries. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like hassio). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -To register your config flow handler with Home Assistant, register it with the config entries `HANDLERS` registry: - -```python -from homeassistant import config_entries, data_entry_flow - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): -``` - -> Temporarily, all config flow handlers will also need to add their component name to the `FLOWS` constant in `homeassistant/config_entries.py`. We are working on automating discovery. - -## Initializing a config flow from an external source - -You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing the config entry: - -```python -await hass.config_entries.flow.async_init( - 'hue', source=data_entry_flow.SOURCE_DISCOVERY, data=discovery_info) -``` - -The config flow handler will need to add a step to support the given source. The step should follow the same return values as a normal step. - -```python -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` - -If the result of the step is to show a form, the user will be able to continue -the flow from the config panel. - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` diff --git a/website/versioned_docs/version-0.72/config_entries_index.md b/website/versioned_docs/version-0.72/config_entries_index.md deleted file mode 100644 index 11af916f..00000000 --- a/website/versioned_docs/version-0.72/config_entries_index.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Config Entries -sidebar_label: Introduction -id: version-0.72-config_entries_index -original_id: config_entries_index ---- - -Config Entries are configuration data that are persistently stored by Home Assistant. A config entry is created by a user via the UI. The UI flow is powered by a [config flow handler](config_entries_config_flow_handler.md) as defined by the component. - -## Setting up an entry - -During startup, Home Assistant first call the [normal component setup](https://developers.home-assistant.io/docs/en/creating_component_index.html), -and then call the method `async_setup_entry(hass, entry)` for each entry. If a new Config Entry is -created at runtime, Home Assistant will also call `async_setup_entry(hass, entry)` ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L119)). - -#### For platforms - -If a component includes platforms, it will need to forward the Config Entry to the platform. This can -be done by calling the forward function on the config entry manager ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/bridge.py#L81)): - -```python -# Use `hass.async_add_job` to avoid a circular dependency between the platform and the component -hass.async_add_job(hass.config_entries.async_forward_entry_setup(config_entry, 'light')) -``` - -For a platform to support config entries, it will need to add a setup entry method ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/light/hue.py#L60)): - -```python -async def async_setup_entry(hass, config_entry, async_add_devices): -``` - -## Unloading entries - -Components can optionally support unloading a config entry. When unloading an entry, the component needs -to clean up all entities, unsubscribe any event listener and close all connections. To implement this, -add `async_unload_entry(hass, entry)` to your component ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L136)). - -Platforms will not need to add any logic for unloading a config entry. The entity component will take care of this. -If you need to clean up resources used for an entity, implement the `async_will_remove_from_hass` method on the Entity ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/media_player/cast.py#L313)). diff --git a/website/versioned_docs/version-0.72/configuration_yaml_index.md b/website/versioned_docs/version-0.72/configuration_yaml_index.md deleted file mode 100644 index 30e37630..00000000 --- a/website/versioned_docs/version-0.72/configuration_yaml_index.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Configuration.yaml -sidebar_label: Introduction -id: version-0.72-configuration_yaml_index -original_id: configuration_yaml_index ---- - -`configuration.yaml` is a configuration file defined by the user. It is automatically created by Home Assistant on first launch. It defines which components to load. - -## Pre-processing - -Home Assistant will do some pre-processing on the config based on the components that are specified to load. - -### CONFIG_SCHEMA - -If a component defines a variable `CONFIG_SCHEMA`, the config object that is passed in will be the result of running the config through `CONFIG_SCHEMA`. `CONFIG_SCHEMA` should be a voluptuous schema. - -### PLATFORM_SCHEMA - -If a component defines a variable `PLATFORM_SCHEMA`, the component will be treated as an entity component. The configuration of entity components is a list of platform configurations. - -Home Assistant will gather all platform configurations for this component. It will do so by looking for configuration entries under the domain of the component (ie `light`) but also under any entry of domain + extra text. - -While gathering the platform configs, Home Assistant will validate them. It will see if the platform exists and if the platform defines a PLATFORM_SCHEMA, validate against that schema. If not defined, it will validate the config against the PLATFORM_SCHEMA defined in the component. Any configuration that references non existing platforms or contains invalid config will be removed. - -The following `configuration.yaml`: - -```yaml -unrelated_component: - some_key: some_value - -switch: - platform: example1 - -switch living room: - - platform: example2 - some_config: true - - platform: invalid_platform -``` - -will be passed to the component as - -```python -{ - "unrelated_component": { - "some_key": "some_value" - }, - "switch": [ - { - "platform": "example1" - }, - { - "platform": "example2, - "some_config": True - } - ] -} -``` diff --git a/website/versioned_docs/version-0.72/creating_component_code_review.md b/website/versioned_docs/version-0.72/creating_component_code_review.md deleted file mode 100644 index b1f4a4d7..00000000 --- a/website/versioned_docs/version-0.72/creating_component_code_review.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Checklist for creating a component -id: version-0.72-creating_component_code_review -original_id: creating_component_code_review ---- - -A checklist of things to do when you're adding a new component. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 1. Requirements - - 1. Requirement version pinned: `REQUIREMENTS = ['phue==0.8.1']` - 2. We no longer want requirements hosted on GitHub. Please upload to PyPi. - 3. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Configuration - - 1. Voluptuous schema present for config validation - 2. Default parameters specified in voluptuous schema, not in `setup(…)` - 3. Schema using as many generic config keys as possible from `homeassistant.const` - 4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`. - 5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation` - 6. Never depend on users adding things to `customize` to configure behavior inside your component. - -### 3. Component/platform communication - - 1. If you need to share global data with platforms, use the dictionary `hass.data`. `hass.data[DATA_XY]` while `XY` is the component is preferred over `hass.data[DOMAIN]`. - 2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`. diff --git a/website/versioned_docs/version-0.72/creating_component_deps_and_reqs.md b/website/versioned_docs/version-0.72/creating_component_deps_and_reqs.md deleted file mode 100644 index abcb7d23..00000000 --- a/website/versioned_docs/version-0.72/creating_component_deps_and_reqs.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: Requirements & Dependencies -id: version-0.72-creating_component_deps_and_reqs -original_id: creating_component_deps_and_reqs ---- - -Home Assistant allows components and platforms to specify their dependencies and requirements using the variables `DEPENDENCIES` and `REQUIREMENTS`. Both are lists that contain strings. - -## Dependencies - -Dependencies are other Home Assistant components that should be setup before the platform is loaded. An example is the MQTT sensor component, which requires an active connection to an MQTT broker. If Home Assistant is unable to load and setup the MQTT component, it will not setup the MQTT sensor component. - -```python -DEPENDENCIES = ['mqtt'] -``` - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you running in a virtual environment. This will make sure that all requirements are present at startup. If steps fails like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is a list of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v0.6.12: - -```python -REQUIREMENTS = ['pychromecast==0.6.12'] -``` - -During development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using pychromecast as an example: - -* `pip install pychromecast==0.6.13 --target ~/.homeassistant/deps` -* `hass --skip-pip` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is currently in `REQUIREMENTS`. - -If you need to make changes to a requirement to support your component, it's also possible to `pip install` from a checkout of the requirement. - -* `git clone https://github.com/balloob/pychromecast.git` -* `pip install ./pychromecast` -* `hass --skip-pip` - -For testing and development purposes you can also to point to a hosted package in the form of an archive (zip/tar.gz) file as a requirement. GitHub provides archive files for a specific branch, release or even a specific commit. To do that the string in `REQUIREMENTS` needs to be composed of two parts: - -* an URL pointing to the archive file (e.g. `https://github.com/my/repo/archive/branch-x.zip`) -* a hashtag and `pip` string (as described above) to declare what package and version that archive file contains - -Note: Components and platforms included in Home Assistant should point to published PyPI packages. This ensures that the unit tests will not be slowed down as they can be cached. - -For example, the Neato robot vacuum components specifies the v.0.0.5 release on GitHub as a requirement that gets installed as pybotvac version 0.0.5 (`pybotvac==0.0.5`). - -```python -REQUIREMENTS = ['https://github.com/jabesq/pybotvac/archive/v0.0.5.zip#pybotvac==0.0.5'] -``` diff --git a/website/versioned_docs/version-0.72/creating_component_discovery.md b/website/versioned_docs/version-0.72/creating_component_discovery.md deleted file mode 100644 index fd79025a..00000000 --- a/website/versioned_docs/version-0.72/creating_component_discovery.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Component Discovery -id: version-0.72-creating_component_discovery -original_id: creating_component_discovery ---- - -> This option is only available for built-in components. - -Home Assistant has a discovery service running in the background to discover new devices. Whenever a new device is discovered, a `SERVICE_DISCOVERED` event will be fired with the found service and the information. The `discovery` component has some knowledge about which components handle which type of services and will ensure those are loaded and listening before firing the `SERVICE_DISCOVERED` event. - -### Add discovery instructions - -Device discovery for Home Assistant has been extracted into an external library called [NetDisco](https://github.com/home-assistant/netdisco). This library is integrated using [the `discovery` component](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery.py) and scans the network in intervals for uPnP and zeroconf/mDNS services. - -To have your device be discovered, you will have to extend the NetDisco library to be able to find your device. This is done by adding a new discoverable. [See the repository for examples of existing discoverable.](https://github.com/home-assistant/netdisco/tree/master/netdisco/discoverables) - -### Listening to `SERVICE_DISCOVERED` events - -From your component, you will have to set up the listening for specific services. Given below is an example how one would listen for a discovered AwesomeDevice: - -```python -from homeassistant.components.discovery import SERVICE_AWESOMEDEVICE -from homeassistant.helpers import discovery - -DOMAIN = 'awesomedevice' - -DEPENDENCIES = ['http'] - -def setup(hass, config): - cfg = config.get(DOMAIN) - - def device_discovered(service, info): - """ Called when a Awesome device has been discovered. """ - print("Discovered a new Awesome device: {}".format(info)) - - discovery.listen( - hass, SERVICE_AWESOMEDEVICE, device_discovered) - - return True -``` - -### Auto-loading your component upon discovery - -The `discovery` component is capable of setting up your components before firing the `EVENT_PLATFORM_DISCOVERED` event. To do this you will have to update the [`SERVICE_HANDLERS`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery.py#L40) constant in [the `discovery` component](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery.py): - -```python -SERVICE_AWESOMEDEVICE = 'awesomedevice' - -SERVICE_HANDLERS = { - ... - SERVICE_AWESOMEDEVICE: ('awesomedevice', None), -} -``` diff --git a/website/versioned_docs/version-0.72/creating_component_events.md b/website/versioned_docs/version-0.72/creating_component_events.md deleted file mode 100644 index c642ae59..00000000 --- a/website/versioned_docs/version-0.72/creating_component_events.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Handling events -id: version-0.72-creating_component_events -original_id: creating_component_events ---- - -Home Assistant has different ways of responding to events that occur in Home Assistant. These have been organized in [helper methods](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/event.py). Examples are `track_state_change`, `track_point_in_time`, `track_time_change`. diff --git a/website/versioned_docs/version-0.72/creating_component_generic_discovery.md b/website/versioned_docs/version-0.72/creating_component_generic_discovery.md deleted file mode 100644 index 5ec6f04b..00000000 --- a/website/versioned_docs/version-0.72/creating_component_generic_discovery.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Generic Platform Discovery -id: version-0.72-creating_component_generic_discovery -original_id: creating_component_generic_discovery ---- - -New controller or hub components often need to add platforms in sub-components (i.e. Lights & Switches) without additional configuration. -This can be achieved using the `load_platform` or `async_load_platform` methods from `homeassistant.helpers.discovery`: - -```python -def load_platform(hass, component, platform, discovered=None, hass_config=None) -``` - -From more info on how this works, refer to the [load_platform](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/discovery.py#L136) method. - -### Example - -Say you need to implement your new MyFlashyHub that controls both Switches & Lights, you can follow these steps: - -Configuration required for your new hub component: - -```yaml -myflashyhub: - example: setting -``` - -The source for your component can be located in your configuration directory for now: - -```bash -~/.homeassistant/custom_components/myflashyhub.py -~/.homeassistant/custom_components/light/myflashyhub.py -~/.homeassistant/custom_components/switch/myflashyhub.py -``` - -In the hub component `myflashyhub.py` you can call your light and switch components. To pass any non-serializable information to the platforms in the sub-component, you can use a global variable. - -```python -from homeassistant.helpers.discovery import load_platform -DOMAIN = 'myflashyhub' - -DATA_MFH = 'MFH' - -def setup(hass, config): - """Your controller/hub specific code.""" - hass.data[DATA_MFH] = SomeObjectToInitialiseGlobal() - - #--- snip --- - load_platform(hass, 'light', DOMAIN) - load_platform(hass, 'switch', DOMAIN, {'optional': 'arguments'}) -``` - -Add your custom device specific code to the `setup_platform` method in `light/myflashyhub.py` and `switch/myflashyhub`. - -```python -import custom_components.myflashyhub as myflashyhub - -# 'switch' will receive discovery_info={'optional': 'arguments'} -# as passed in above. 'light' will receive discovery_info=None -def setup_platform(hass, config, add_devices, discovery_info=None): - """Your switch/light specific code.""" - # You can now use hass.data[myflashyhub.DATA_MFH] -``` - - -The `load_platform` method allows the platforms to be loaded without the need for any additional platform entries in your `configuration.yaml` file, which normally would have been: - -```yaml -#light: -# platform: myflashyhub -#switch: -# platform: myflashyhub -``` diff --git a/website/versioned_docs/version-0.72/creating_component_index.md b/website/versioned_docs/version-0.72/creating_component_index.md deleted file mode 100644 index 60c3d6db..00000000 --- a/website/versioned_docs/version-0.72/creating_component_index.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Creating components -sidebar_label: Introduction -id: version-0.72-creating_component_index -original_id: creating_component_index ---- - -Alright, you're ready to make your first component. AWESOME. Don't worry, we've tried hard to keep it as easy as possible. - -### Example component - -Add `hello_state:` to your `configuration.yaml` file and create a file `/custom_components/hello_state.py` with the below code to test it locally. - -```python -DOMAIN = 'hello_state' - -def setup(hass, config): - hass.states.set('hello.world', 'Paulus') - - return True -``` diff --git a/website/versioned_docs/version-0.72/creating_component_loading.md b/website/versioned_docs/version-0.72/creating_component_loading.md deleted file mode 100644 index 25c8617b..00000000 --- a/website/versioned_docs/version-0.72/creating_component_loading.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Loading your components -id: version-0.72-creating_component_loading -original_id: creating_component_loading ---- - -A component will be loaded on start if a section (ie. `light:`) for it exists in the config file. A component can also be loaded if another component is loaded that depends on it. When loading a component Home Assistant will check the following paths: - - * `/custom_components/` - * `homeassistant/components/` (built-in components) - -Once loaded, a component will only be setup if all dependencies can be loaded and are able to setup. Keep an eye on the logs to see if your component could be loaded and initialized. - -> You can override a built-in component by having a component with the same name in your config/custom_components folder. If the built-in component is inside a subfolder, take care to place your customization in a folder with the same name in config/custom_components/*folder*. Note that overriding built-in components is not recommended and will probably break things! - -> Home Assistant will use the directory that contains your config file as the directory that holds your customizations. By default this is the config folder in your current work directory. You can use a different folder by running Home Assistant with the --config argument: python3 homeassistant --config /YOUR/CONFIG/PATH/. diff --git a/website/versioned_docs/version-0.72/creating_component_states.md b/website/versioned_docs/version-0.72/creating_component_states.md deleted file mode 100644 index 671e0895..00000000 --- a/website/versioned_docs/version-0.72/creating_component_states.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Handling states -id: version-0.72-creating_component_states -original_id: creating_component_states ---- - -It is the responsibility of the component to maintain the states of the devices in your domain. Each device should be a single state and, if possible, a group should be provided that tracks the combined state of the devices. - -A state can have several attributes that will help the frontend in displaying your state: - -- `friendly_name`: this name will be used as the name of the device -- `entity_picture`: this picture will be shown instead of the domain icon -- `unit_of_measurement`: this will be appended to the state in the interface -- `hidden`: This is a suggestion to the frontend on if the state should be hidden - -These attributes are defined in [homeassistant.helpers.entity](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/entity.py#L180). - diff --git a/website/versioned_docs/version-0.72/creating_platform_code_review.md b/website/versioned_docs/version-0.72/creating_platform_code_review.md deleted file mode 100644 index a226fc51..00000000 --- a/website/versioned_docs/version-0.72/creating_platform_code_review.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Checklist for creating a platform -id: version-0.72-creating_platform_code_review -original_id: creating_platform_code_review ---- - -A checklist of things to do when you're adding a new platform. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 1. Requirements - - 1. Requirement version should be pinned: `REQUIREMENTS = ['phue==0.8.1']` - 2. We no longer want requirements hosted on GitHub. Please upload to PyPi. - 3. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Dependencies - - 1. If you depend on a component for the connection, add it to your dependencies: `DEPENDENCIES = ['nest']` - -### 3. Configuration - - 1. Voluptuous schema present for config validation - 2. Voluptuous schema extends schema from component
(e.g., `light.hue.PLATFORM_SCHEMA` extends `light.PLATFORM_SCHEMA`) - 3. Default parameters specified in voluptuous schema, not in `setup_platform(…)` - 4. Your `PLATFORM_SCHEMA` should use as many generic config keys as possible from `homeassistant.const` - ```python - import voluptuous as vol - - from homeassistant.const import CONF_FILENAME, CONF_HOST - from homeassistant.components.light import PLATFORM_SCHEMA - import homeassistant.helpers.config_validation as cv - - CONF_ALLOW_UNREACHABLE = 'allow_unreachable' - DEFAULT_UNREACHABLE = False - - PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_ALLOW_UNREACHABLE, - default=DEFAULT_UNREACHABLE): cv.boolean, - vol.Optional(CONF_FILENAME): cv.string, - }) - ``` - 5. Never depend on users adding things to `customize` to configure behavior inside your platform. - -### 4. Setup Platform - - 1. Test if passed in info (user/pass/host etc.) works. - 2. Group your calls to `add_devices` if possible. - 3. If platform adds extra services, format should be `._`. - -### 5. Entity - - 1. Extend entity from component, e.g., `class HueLight(Light)`. - 2. Avoid passing in `hass` as a parameter to the entity. When the entity has been added to Home Assistant, `hass` will be set on the entity by the helper in entity_platform.py. This means you can access `hass` as `self.hass` inside the entity. - 3. Do not call `update()` in constructor, use `add_devices(devices, True)` instead. - 4. Do not do any I/O inside properties. Cache values inside `update()` instead. - 5. The state and/or attributes should not contain relative time since something happened. Instead it should store UTC timestamps. - -### 6. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - -```python -# bad -status = requests.get(url('/status')) - -# good -from phue import Bridge -bridge = Bridge(…) -status = bridge.status() -``` diff --git a/website/versioned_docs/version-0.72/creating_platform_example_light.md b/website/versioned_docs/version-0.72/creating_platform_example_light.md deleted file mode 100644 index d10d758f..00000000 --- a/website/versioned_docs/version-0.72/creating_platform_example_light.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: Example light platform -id: version-0.72-creating_platform_example_light -original_id: creating_platform_example_light ---- - -This example is for adding support for the imaginary Awesome Lights. It shows the different best practices for developing a platform. - -Similar to Example Sensor Platform, copy the code below, and create it as a file in `/custom_components/light/awesomelights.py`. - -Add the following to your configuration.yaml: - -```yaml -light: - - platform: awesomelights - host: HOST_HERE - username: USERNAME_HERE - password: PASSWORD_HERE_OR_secrets.yaml -``` - -Note the `platform` name matches the filename for the source code. - -```python -import logging - -import voluptuous as vol - -# Import the device class from the component that you want to support -from homeassistant.components.light import ATTR_BRIGHTNESS, Light, PLATFORM_SCHEMA -from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD -import homeassistant.helpers.config_validation as cv - -# Home Assistant depends on 3rd party packages for API specific code. -REQUIREMENTS = ['awesome_lights==1.2.3'] - -_LOGGER = logging.getLogger(__name__) - -# Validation of the user's configuration -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_USERNAME, default='admin'): cv.string, - vol.Optional(CONF_PASSWORD): cv.string, -}) - - -def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the Awesome Light platform.""" - import awesomelights - - # Assign configuration variables. The configuration check takes care they are - # present. - host = config.get(CONF_HOST) - username = config.get(CONF_USERNAME) - password = config.get(CONF_PASSWORD) - - # Setup connection with devices/cloud - hub = awesomelights.Hub(host, username, password) - - # Verify that passed in configuration works - if not hub.is_valid_login(): - _LOGGER.error("Could not connect to AwesomeLight hub") - return - - # Add devices - add_devices(AwesomeLight(light) for light in hub.lights()) - - - -class AwesomeLight(Light): - """Representation of an Awesome Light.""" - - def __init__(self, light): - """Initialize an AwesomeLight.""" - self._light = light - self._name = light.name - self._state = None - self._brightness = None - - @property - def name(self): - """Return the display name of this light.""" - return self._name - - @property - def brightness(self): - """Return the brightness of the light. - - This method is optional. Removing it indicates to Home Assistant - that brightness is not supported for this light. - """ - return self._brightness - - @property - def is_on(self): - """Return true if light is on.""" - return self._state - - def turn_on(self, **kwargs): - """Instruct the light to turn on. - - You can skip the brightness part if your light does not support - brightness control. - """ - self._light.brightness = kwargs.get(ATTR_BRIGHTNESS, 255) - self._light.turn_on() - - def turn_off(self, **kwargs): - """Instruct the light to turn off.""" - self._light.turn_off() - - def update(self): - """Fetch new state data for this light. - - This is the only method that should fetch new data for Home Assistant. - """ - self._light.update() - self._state = self._light.is_on() - self._brightness = self._light.brightness -``` diff --git a/website/versioned_docs/version-0.72/creating_platform_example_sensor.md b/website/versioned_docs/version-0.72/creating_platform_example_sensor.md deleted file mode 100644 index b7f06c49..00000000 --- a/website/versioned_docs/version-0.72/creating_platform_example_sensor.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Example sensor platform -id: version-0.72-creating_platform_example_sensor -original_id: creating_platform_example_sensor ---- - -This is a minimum implementation of a platform for the sensor component. - -### Installation - -Copy the code below and create it as a file in `/custom_components/sensor/example.py`. - -Add the following to your `configuration.yaml` file: - -```yaml -# Example configuration.yaml entry -sensor: - platform: example -``` - -### Code - -```python -from homeassistant.const import TEMP_CELSIUS -from homeassistant.helpers.entity import Entity - - -def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the sensor platform.""" - add_devices([ExampleSensor()]) - - -class ExampleSensor(Entity): - """Representation of a Sensor.""" - - def __init__(self): - """Initialize the sensor.""" - self._state = None - - @property - def name(self): - """Return the name of the sensor.""" - return 'Example Temperature' - - @property - def state(self): - """Return the state of the sensor.""" - return self._state - - @property - def unit_of_measurement(self): - """Return the unit of measurement.""" - return TEMP_CELSIUS - - def update(self): - """Fetch new state data for the sensor. - - This is the only method that should fetch new data for Home Assistant. - """ - self._state = 23 -``` diff --git a/website/versioned_docs/version-0.72/creating_platform_index.md b/website/versioned_docs/version-0.72/creating_platform_index.md deleted file mode 100644 index e51dad8f..00000000 --- a/website/versioned_docs/version-0.72/creating_platform_index.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Adding support for a new platform -sidebar_label: Introduction -id: version-0.72-creating_platform_index -original_id: creating_platform_index ---- - -Components that interact with devices are called "[Entity Components](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/entity_component.py)." They are structured in core and platform logic, which means different brands can use the same logic to handle a light. - -For example, the built-in `switch` component consists of various platforms in [`homeassistant/components/switch/`](https://github.com/home-assistant/home-assistant/tree/master/homeassistant/components/switch). The file `__init__.py` contains the core logic of all platforms and the `vendor_name.py` files contain only the relevant platform code. - -If you're planning to add support for a new type of device to an existing component, you can get away with only writing platform logic. Have a look at how the component works with other platforms and create a similar file for the platform that you want to add: - - - [Example sensor platform](creating_platform_example_sensor.md): hello world of platforms. - - [Example light platform](creating_platform_example_light.md): showing best practices. - -### Interfacing with devices - -One Home Assistant rule is that platform logic should never interface directly with devices. Instead, use a third-party Python 3 library. This way, Home Assistant can share code with the Python community and keep the project maintainable. - -To integrate the third-party library, create an [Entity class](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/entity.py) for your device. Entities are Home Assistant's representations of lights, switches, sensors, etc. and are derived from the [Entity Abstract Class](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/entity.py). This abstract class contains logic for integrating most standard features into your entities, such as visibility, entity IDs, updates, and much more. - -### Requirements and dependencies - -Platforms can specify dependencies and requirements [the same way as components](creating_component_deps_and_reqs.md): - -```python -REQUIREMENTS = ['some-package==2.0.0', 'some-other-package==2.5.0'] -DEPENDENCIES = ['mqtt'] -``` - diff --git a/website/versioned_docs/version-0.72/data_entry_flow_index.md b/website/versioned_docs/version-0.72/data_entry_flow_index.md deleted file mode 100644 index 47084e9a..00000000 --- a/website/versioned_docs/version-0.72/data_entry_flow_index.md +++ /dev/null @@ -1,190 +0,0 @@ ---- -title: Data Entry Flow -sidebar_label: Introduction -id: version-0.72-data_entry_flow_index -original_id: data_entry_flow_index ---- - -Data Entry Flow is a data entry framework that is part of Home Assistant. Data entry is done via data entry flows. A flow can represent a simple login form or a multi-step setup wizard for a component. A Flow Manager is managing all flows that are in progress and handles creation of new flows. - -Data Entry Flow is being used in Home Assistant to create config entries. - -## Flow Manager - -This is the class that manages the flows that are in progress. When instantiating one, you pas in two async callbacks: - -```python -async def async_create_flow(handler, source=source, data=data) -``` - -The manager delegates instantiating of config flow handlers to this async callback. This allows the parent of the manager to define their own way of finding handlers and preparing a handler for instantiation. For example, in the case of the config entry manager, it will make sure that the dependencies and requirements are setup. - -```python -async def async_finish_flow(result) -``` - -This async callback is called when a flow is finished. The result is a dictionary that looks like this: - -```python -{ - # Data schema version of the entry - 'version': 2, - # The result type of the flow - 'type': RESULT_TYPE_CREATE_ENTRY, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # title and data as created by the handler - 'title': 'Some title', - 'data': { - 'some': 'data' - }, - # Source that instantiated the flow - 'source': self.source, -} -``` - -## Config Flow Handler - -Config flow handlers will handle a single flow. A flow contains 1 or more steps. When a flow is instantiated by the user, the `init` step will be called. Each step has three different possible results: "Show Form", "Abort" and "Create Entry". - -At a minimum, each config flow handler will have to define a version number and a step. This doens't have to be `init`, as different steps will be called when instantiated by a non-user (ie discovery). - -The bare minimum config flow: - -```python -from homeassistant import data_entry_flow - -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - # The schema version of the entries that it creates - # Home Assistant will call your migrate method if the version changes - # (this is not implemented yet) - VERSION = 1 - - async def async_step_init(self, user_input=None): - # Do something -``` - -### Show Form - -This result type will show a form to the user to fill in. You define the current step, the schema of the data (using voluptuous) and optionally a dictionary of errors. Title and description of the step will be provided via the translation file. Where this is defined depends on the context of the data entry flow. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_init(self, user_input=None): - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema) - ) -``` - -After the user has filled in the form, the step method will be called again and the user input is passed in. Your step will only be called if the user input passes your data schema. When the user passes in data, you will have to do extra validation of the data. For example, you can verify that the passed in username and password are valid. - -If something is wrong, you can return a dictionary with errors. Each key in the error dictionary refers to a field name that contains the error. Use the key `base` if you want to show an error unrelated to a specific field. The specified errors need to refer to a key in a translation file. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_init(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # See next section on create entry usage - return self.create_entry(…) - - errors['base'] = 'auth_error' - - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema), - errors=errors - ) -``` - -#### Multi-step flows - -If the user input passes validation, you can again return one of the three -return values. If you want to navigate the user to the next step, return the -return value of that step: - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_init(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # Store info to use in next step - self.init_info = user_input - # Return the form of the next step - return await self.async_step_account() - - … -``` - -### Create Entry - -When the result is "Create Entry", an entry will be created and passed to the parent of the flow manager. A success message is shown to the user and the flow is finished. You create an entry by passing a title and data. The title can be used in the UI to indicate to the user which entry it is. Data can be any data type, as long as it is JSON serializable. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_init(self, user_input=None): - return self.create_entry( - title='Title of the entry', - data={ - 'something_special': user_input['username'] - } - ) -``` - -### Abort - -When a flow cannot be finished, you need to abort it. This will finish the flow and inform the user that the flow has finished. Reasons for a flow to not be able to finish can be that a device is already configured or not compatible with Home Assistant. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_init(self, user_input=None): - return self.async_abort( - reason='not_supported' - ) -``` - -## Translations - -Data entry flows depend on translations for showing the text in the forms. It depends on the parent of a data entry flow manager where this is stored. - -## Initializing a config flow from an external source - -You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing a flow: - -```python -await flow_mgr.async_init('hue', source=data_entry_flow.SOURCE_DISCOVERY, data=discovery_info) -``` - -The config flow handler will not start with the `init` step. Instead, it will be instantiated with a step name equal to the source. The step should follow the same return values as a normal step. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` diff --git a/website/versioned_docs/version-0.72/dev_101_config.md b/website/versioned_docs/version-0.72/dev_101_config.md deleted file mode 100644 index 2b94daa4..00000000 --- a/website/versioned_docs/version-0.72/dev_101_config.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Using Config -id: version-0.72-dev_101_config -original_id: dev_101_config ---- - -Based on where you are in the code, `config` can mean various things. - -### On the hass object - -On the hass object is an instance of the Config class. The Config class contains the users preferred units, the path to the config directory and which components are loaded. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config) - -### Config passed into component setup - -The `config` parameter passed to a component setup is a dictionary containing all of the user supplied configuration. The keys of the dictionary are the component names and the value is another dictionary with the component configuration. - -The object will have already been validated using your `CONFIG_SCHEMA` or `PLATFORM_SCHEMA` if available. If you have defined a `PLATFORM_SCHEMA`, all references to your component (ie `light 2:` etc) will have been changed to be accessible as a list under `config[DOMAIN]`. - -If your configuration file contains the following lines: - -```yaml -example: - host: paulusschoutsen.nl -``` - -Then in the setup method of your component you will be able to refer to `config['example']['host']` to get the value `paulusschoutsen.nl`. - -### Passed into platform setup - -The `config` parameter passed to a platform setup function is only the config for that specific platform. diff --git a/website/versioned_docs/version-0.72/dev_101_events.md b/website/versioned_docs/version-0.72/dev_101_events.md deleted file mode 100644 index 05ca0f0e..00000000 --- a/website/versioned_docs/version-0.72/dev_101_events.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Using Events -id: version-0.72-dev_101_events -original_id: dev_101_events ---- - -The core of Home Assistant is driven by events. That means that if you want to respond to something happening, you'll have to respond to events. Most of the times you won't interact directly with the event system but use one of the [event listener helpers][helpers]. - -The event system is very flexible. There are no limitations on the event type, as long as it's a string. Each event can contain data. The data is a dictionary that can contain any data as long as it's JSON serializable. This means that you can use number, string, dictionary and list. - -[List of events that Home Assistant fires.][object] - -## Firing events - -To fire an event, you have to interact with the event bus. The event bus is available on the Home Assistant instance as `hass.bus`. - -Example component that will fire an event when loaded. - -```python -DOMAIN = 'hello_event' - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - # Fire event my_cool_event with event data answer=42 - hass.bus.fire('my_cool_event', { - 'answer': 42 - }) -``` - -## Listening to events - -Most of the times you'll not be firing events but instead listen to events. For example, the state change of an entity is broadcasted as an event. - -```python -DOMAIN = 'hello_event' - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - count = 0 - - # Listener to handle fired events - def handle_event(event): - nonlocal count - count += 1 - print('Total events received:', count) - - # Listen for when my_cool_event is fired - hass.bus.listen('my_cool_event', handle_event) -``` - -### Helpers - -Home Assistant comes with a lot of bundled helpers to listen to specific types of event. There are helpers to track a point in time, to track a time interval, a state change or the sun set. [See available methods.][helpers] - -[helpers]: https://dev-docs.home-assistant.io/en/master/api/helpers.html#module-homeassistant.helpers.event -[object]: https://www.home-assistant.io/docs/configuration/events/ diff --git a/website/versioned_docs/version-0.72/dev_101_hass.md b/website/versioned_docs/version-0.72/dev_101_hass.md deleted file mode 100644 index 24924f19..00000000 --- a/website/versioned_docs/version-0.72/dev_101_hass.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Hass object -id: version-0.72-dev_101_hass -original_id: dev_101_hass ---- - -While developing Home Assistant you will see a variable that is everywhere: `hass`. This is the Home Assistant instance that will give you access to all the various parts of the system. - -### The `hass` object - -The Home Assistant instance contains four objects to help you interact with the system. - -| Object | Description | -| ------ | ----------- | -| `hass` | This is the instance of Home Assistant. Allows starting, stopping and enqueing new jobs. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.HomeAssistant) -| `hass.config` | This is the core configuration of Home Assistant exposing location, temperature preferences and config directory path. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config) -| `hass.states` | This is the StateMachine. It allows you to set states and track when they are changed. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.StateMachine) | -| `hass.bus` | This is the EventBus. It allows you to trigger and listen for events. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.EventBus) | -| `hass.services` | This is the ServiceRegistry. It allows you to register services. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.ServiceRegistry) | - -### Where to find `hass` - -Depending on what you're writing, there are different ways the `hass` object is made available. - -**Component**
-Passed into `setup(hass, config)` or `async_setup(hass, config)`. - -**Platform**
-Passed into `setup_platform(hass, config, add_devices, discovery_info=None)` or `async_setup_platform(hass, config, async_add_devices, discovery_info=None)`. - -**Entity**
-Available as `self.hass` once the entity has been added via the `add_devices` callback inside a platform. diff --git a/website/versioned_docs/version-0.72/dev_101_index.md b/website/versioned_docs/version-0.72/dev_101_index.md deleted file mode 100644 index 6c0fea53..00000000 --- a/website/versioned_docs/version-0.72/dev_101_index.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Development 101 -sidebar_label: Introduction -id: version-0.72-dev_101_index -original_id: dev_101_index ---- - -The goal of development 101 is to get you familiar with the basics of developing for Home Assistant. Before we start, please make sure you familiarize yourself with the [architecture](architecture_index.md). - -To get our code running inside Home Assistant we're going to create a custom component. The first step is to locate your config folder. You can find the path to your config folder by opening the Home Assistant frontend, click on the service developer tool icon. It's the path after the text "Path to configuration.yaml". - -Inside your configuration directory create a new folder called `custom_components`. It might be that one already exists, that's fine too. This is the folder that Home Assistant will look at when looking for custom code. - -> The Home Assistant API has two variants: a synchronous and an asynchronous version (asyncio). This development course will focus on the synchronous version. - -To verify that everything is working correctly, let's create a small Hello World component. To do so, create a file called `hello_world.py` in your custom components folder. Copy paste the following content to it: - -```python -# The domain of your component. Equal to the filename of your component. -DOMAIN = "hello_world" - - -def setup(hass, config): - """Setup the hello_world component.""" - # States are in the format DOMAIN.OBJECT_ID. - hass.states.set('hello_world.Hello_World', 'Works!') - - # Return boolean to indicate that initialization was successfully. - return True -``` - -Last step is to add `hello_world:` entry to your `configuration.yaml` file. - -```yaml -# Hello World component -hello_world: -``` - -After running `hass`, we should see log entries stating that `hello_world` component was loaded. What is more, additional state card shall appear within main panel. - -```log -2018-04-03 21:44:20 INFO (MainThread) [homeassistant.loader] Loaded hello_world from custom_components.hello_world -2018-04-03 21:44:20 INFO (MainThread) [homeassistant.setup] Setting up hello_world -``` - -State card showing that Hello World component is working as intended. diff --git a/website/versioned_docs/version-0.72/dev_101_services.md b/website/versioned_docs/version-0.72/dev_101_services.md deleted file mode 100644 index dc206fe0..00000000 --- a/website/versioned_docs/version-0.72/dev_101_services.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Using Services -id: version-0.72-dev_101_services -original_id: dev_101_services ---- - -This is a simple "hello world" example to show the basics of registering a service. To use this example, create the file `/custom_components/hello_service.py` and copy the below example code. - -Services can be called from automation and from the service "Developer tools" in the frontend. - -```python -# The domain of your component. Should be equal to the name of your component. -DOMAIN = 'hello_service' - -ATTR_NAME = 'name' -DEFAULT_NAME = 'World' - - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - def handle_hello(call): - name = call.data.get(ATTR_NAME, DEFAULT_NAME) - - hass.states.set('hello_service.hello', name) - - hass.services.register(DOMAIN, 'hello', handle_hello) - - # Return boolean to indicate that initialization was successfully. - return True -``` - -Load the component by adding the following to your `configuration.yaml`. When your component is loaded, a new service should be available to call. - -```yaml -# configuration.yaml entry -hello_service: -``` - -Open the frontend and in the sidebar, click the first icon in the developer tool section. This will open the Call Service developer tool. On the right, find your service and click on it. This will automatically fill in the correct values. - -Pressing "Call Service" will now call your service without any parameters. This will cause your service to create a state with the default name 'World'. If you want to specify the name, you have to specify parameters. Add the following JSON as Service Data and press "Call Service again". - -```json -{ - "name": "Planet" -} -``` - -The service will now overwrite the previous state with "Planet". diff --git a/website/versioned_docs/version-0.72/dev_101_states.md b/website/versioned_docs/version-0.72/dev_101_states.md deleted file mode 100644 index 5d0723c2..00000000 --- a/website/versioned_docs/version-0.72/dev_101_states.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -title: Using States -id: version-0.72-dev_101_states -original_id: dev_101_states ---- - -Home Assistant keeps track of the states of entities in a state machine. The state machine has very few requirements: - - - Each state is related to an entity identified by an entity id. This id is made up of a domain and an object id. For example `light.kitchen_ceiling`. You can make up any combination of domain and object id, even overwriting existing states. - - Each state has a primary attribute that describes the state of the entity. In the case of a light this could be for example "on" and "off". You can store anything you want in the state, as long as it's a string (will be converted if it's not). - - You can store more information about an entity by setting attributes. Attributes is a dictionary that can contain any data that you want. The only requirement is that it's JSON serializable, so you're limited to numbers, strings, dictionaries and lists. - -[Description of the state object.](https://www.home-assistant.io/docs/configuration/state_object/) - -## Using states in your component - -This is a simple tutorial/example on how to create and set states. We will do our work in a component called "hello_state". The purpose of this component is to display a given text in the frontend. - -To get started, create the file `/custom_components/hello_state.py` and copy the below example code. - -```python -""" -Support for showing text in the frontend. - -For more details about this component, please refer to the documentation at -https://home-assistant.io/cookbook/python_component_basic_state/ -""" -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = 'hello_state' -DEPENDENCIES = [] - -def setup(hass, config): - """Setup the Hello State component. """ - _LOGGER.info("The 'hello state' component is ready!") - - return True -``` - -1. In the file header we decided to add some details: A short description and the link to the documentation. -2. We want to do some logging. This means that we import the Python logging module and create an alias. -3. The component name is equal to the domain name. -4. At the moment this component has no dependencies. For detail check [dependencies](creating_component_deps_and_reqs.md#dependencies) section. -5. The `setup` function will take care of the initialization of our component. - The component will only write a log message. Keep in mind for later that you have several options for the severity: - - - `_LOGGER.info(msg)` - - `_LOGGER.warning(msg)` - - `_LOGGER.error(msg)` - - `_LOGGER.critical(msg)` - - `_LOGGER.exception(msg)` - -7. We return `True` if everything is ok. - -Add the component to your `configuration.yaml` file. - -```yaml -hello_state: -``` - -After a start or a restart of Home Assistant the component will create an entry in the log. - -```bash -16-03-12 14:16:42 INFO (MainThread) [custom_components.hello_state] The 'hello state' component is ready! -``` - -The next step is the introduction of configuration options. A user can pass configuration options to our component via `configuration.yaml`. To use them we'll use the passed in `config` variable to our `setup` method. - -```python -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = 'hello_state' -DEPENDENCIES = [] - -CONF_TEXT = 'text' -DEFAULT_TEXT = 'No text!' - -def setup(hass, config): - """Set up the Hello State component. """ - # Get the text from the configuration. Use DEFAULT_TEXT if no name is provided. - text = config[DOMAIN].get(CONF_TEXT, DEFAULT_TEXT) - - # States are in the format DOMAIN.OBJECT_ID - hass.states.set('hello_state.Hello_State', text) - - return True -``` - -To use the latest feature of our component, update the entry in your `configuration.yaml` file. - -```yaml -hello_state: - text: 'Hello, World!' -``` - -Thanks to `DEFAULT_TEXT` variable the component will launch even if no `text:` field is used in the `configuration.yaml` file. Quite often there are variables which are required. It's important to check if all mandatory configuration variables are provided. If not, the setup should fail. We will use `voluptuous` as a helper to achieve this. The next listing shows the essential parts. - -```python -import voluptuous as vol - -import homeassistant.helpers.config_validation as cv - -CONFIG_SCHEMA = vol.Schema({ - DOMAIN: vol.Schema({ - vol.Required(CONF_TEXT): cv.string, - }) -}, extra=vol.ALLOW_EXTRA) -``` - -Now, when `text:` is missing from the config, Home Assistant will alert the user and not setup your component. - -After a start or a restart of Home Assistant the component will be visible in the frontend if the `configuration.yaml` file is up-to-date. - -

- -

- -In order to expose attributes for a platform, you will need to define a property called `device_state_attributes` on the entity class, which will return a dictionary of attributes: - -``` -@property -def device_state_attributes(self): - """Return device specific state attributes.""" - return self._attributes -``` - -> Entities also have a similar property `state_attributes`, which normally doesn't need to be defined by new platforms. This property is used by base components to add standard sets of attributes to a state. Example: The light component uses `state_attributes` to add brightness to the state dictionary. If you are designing a new component, you should define `state_attributes` instead. - -To get your component included in the Home Assistant releases, follow the steps described in the [Submit your work](development_submitting.md) section. Basically you only need to move your component in the `homeassistant/component/` directory of your fork and create a Pull Request. diff --git a/website/versioned_docs/version-0.72/development_catching_up.md b/website/versioned_docs/version-0.72/development_catching_up.md deleted file mode 100644 index 984b00ad..00000000 --- a/website/versioned_docs/version-0.72/development_catching_up.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: Catching up with Reality -id: version-0.72-development_catching_up -original_id: development_catching_up ---- - -If it's taking a while to develop your feature, and you want to catch up with what's in the current Home Assistant `dev` branch, you can use `git rebase`. This will pull the latest Home Assistant changes locally, rewind your commits, bring in the latest changes from Home Assistant, and replay all of your commits on top. - -```bash -# Run this from your feature branch -$ git fetch upstream dev # to pull the latest changes into a local dev branch -$ git rebase upstream/dev # to put those changes into your feature branch before your changes -``` - -If rebase detects conflicts, repeat this process until all changes have been resolved: - -1. `git status` shows you the file with the conflict; edit the file and resolve the lines between `<<<< | >>>>` -3. Add the modified file: `git add ` or `git add .` -4. Continue rebase: `git rebase --continue` -5. Repeat until you've resolved all conflicts - -After rebasing your branch, you will have rewritten history relative to your GitHub fork's branch. When you go to push you will see an error that your history has diverged from the original branch. In order to get your GitHub fork up-to-date with your local branch, you will need to force push, using the following command: - -```bash -# Run this from your feature branch -$ git push origin --force -``` - -Other workflows are covered in detail in the [Github documentation](https://help.github.com/articles/fork-a-repo/). Add an additional `remote` after you clone your fork. - -```bash -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -Then, `git pull --rebase upstream dev`. - diff --git a/website/versioned_docs/version-0.72/development_checklist.md b/website/versioned_docs/version-0.72/development_checklist.md deleted file mode 100644 index 9b73b71b..00000000 --- a/website/versioned_docs/version-0.72/development_checklist.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Development Checklist -id: version-0.72-development_checklist -original_id: development_checklist ---- - - -Before you commit any changes, check your work against these requirements: - -- All dependencies from [pypi](https://pypi.python.org/pypi) are included via the `REQUIREMENTS` variable in your platform or component and only imported inside functions that use them -- New dependencies are added to `requirements_all.txt` (if applicable), using `script/gen_requirements_all.py` -- The `.coveragerc` file is updated to exclude your platform if there are no tests available or your new code uses a third-party library for communication with the device, service, or sensor -- Documentation is developed for [home-assistant.io](/) - * It's OK to start with adding a docstring with configuration details (for example, sample entry for `configuration.yaml` file) to the file header. Visit the [website documentation](https://www.home-assistant.io/developers/documentation/) for more information about contributing to [home-assistant.io](https://github.com/home-assistant/home-assistant.github.io). - diff --git a/website/versioned_docs/version-0.72/development_environment.md b/website/versioned_docs/version-0.72/development_environment.md deleted file mode 100644 index 75a8cd1b..00000000 --- a/website/versioned_docs/version-0.72/development_environment.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.72-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example Centos would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -If you are using Windows as a development platform, make sure that you have the correct Microsoft [Visual C++ build tools](http://landinghub.visualstudio.com/visual-cpp-build-tools) installed. The installation of the most requirements and validation using `tox` will fail if this is not done correctly. Check the [Windows Compilers](https://wiki.python.org/moin/WindowsCompilers) section on the [Python website](https://www.python.org/) for details. - -Due to Home Assistant is mainly designed and developed on Linux distributions it is not recommended to develop on Windows machines. However on Windows 10 machines you should decide to set up a [Linux subsystem](https://docs.microsoft.com/de-de/windows/wsl/install-win10). - -Setup Linux subsystem. - -```bash -$ apt-get update -$ apt-get upgrade -$ echo 'export DISPLAY=:0' >> ~/.bashrc && . ~/.bashrc -$ sudo apt-get install xubuntu-desktop -y -``` - -It is recommended using [PyCharm](https://www.jetbrains.com/pycharm/download/) as debugger. Download and start PyCharm. - -```bash -$ wget https://download.jetbrains.com/python/pycharm-community-20XX.X.tar.gz -$ tar -xzf pycharm-community-20XX.X -$ ./pycharm.sh -``` - -In order to display the PyCharm GUI on Windows you need to run a X-Server like [VcXserv](https://sourceforge.net/projects/vcxsrv/). - -Also, make sure to install or upgrade the `setuptools` Python package. It contains compatibility improvements and adds automatic use of compilers: - -```bash -$ pip install --upgrade setuptools -``` - -### Developing on OS X - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 -``` - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv . -$ source bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation. - -```bash -$ hass -``` - -## Logging - -By default logging in home-assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on. diff --git a/website/versioned_docs/version-0.72/development_guidelines.md b/website/versioned_docs/version-0.72/development_guidelines.md deleted file mode 100644 index be54a8ff..00000000 --- a/website/versioned_docs/version-0.72/development_guidelines.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: Style guidelines -id: version-0.72-development_guidelines -original_id: development_guidelines ---- - -Home Assistant enforces strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. We automatically test every pull request as part of the linting process with [Coveralls](https://coveralls.io/github/home-assistant/home-assistant) and [Travis CI](https://travis-ci.org/home-assistant/home-assistant). - -Summary of the most relevant points: - -- Line length is limited to 79 characters (see below). -- Use 4 spaces per indentation level. We don't use tabs. -- Comments should be full sentences and end with a period. -- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered. -- Constants and the content of lists and dictionaries should be in alphabetical order. -- Avoid trailing whitespace but surround binary operators with a single space. -- Line separator should be set to `LF`. - -The maximum line length comes directly from the [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/#maximum-line-length), and is also used by the Python standard library. All code must pass these linting checks, and no exceptions will be made. There have already been numerous requests to increase the maximum line length, but after evaluating the options, the Home Assistant maintainers have decided to stay at 79 characters. This decision is final. - -Those points may require that you adjust your IDE or editor settings. - -## Our recommendations - -For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code unified. - -### Quotes - -Use single quotes `'` for single word and `"` for multiple words or sentences. - -```python -ATTR_WATERLEVEL = 'level' -CONF_ATTRIBUTION = "Data provided by the WUnderground weather service" -SENSOR_TYPES = { - 'alerts': ['Alerts', None], -} -``` - -### File headers - -The docstring in the file header should contain a link to the documentation to make it easy to find further information, especially about the configuration or details which are not mentioned in the code. - -```python -""" -Support for MQTT lights. - -For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/light.mqtt/ -""" -``` - -### Requirements - -Please place [Platform requirements](creating_platform_code_review.md#1-requirements) right after the imports. - -```python -[...] -from homeassistant.helpers.entity import Entity - -REQUIREMENTS = ['xmltodict==0.11.0'] -``` - -### Log messages - -There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. Try to avoid brackets and additional quotes around the output to make it easier for users to parse the log. A widely style is shown below but you are free to compose the messages as you like. - -```python -_LOGGER.error("No route to device: %s", self._resource) -``` - -```bash -2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18 -``` - -Don't print out wrong API keys, tokens, usernames, or passwords. -Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` in anything else. diff --git a/website/versioned_docs/version-0.72/development_index.md b/website/versioned_docs/version-0.72/development_index.md deleted file mode 100644 index dafb25cf..00000000 --- a/website/versioned_docs/version-0.72/development_index.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Starting with Development -sidebar_label: Introduction -id: version-0.72-development_index -original_id: development_index ---- - -Home Assistant is built from the ground up to be easily extensible using components. Home Assistant uses [Python 3](https://www.python.org/) for the backend and [Polymer (Web components)](https://www.polymer-project.org/) for the frontend. - -Home Assistant is open-source and licensed under [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0). Here are links to the source: - - - [home-assistant](https://github.com/home-assistant/home-assistant): Python server backend. - - [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer): Polymer UI. - -For those new to contributing to open source software, make sure you are familiar with all of the tools and concepts used in Home Assistant before you start. - -When contributing Home Assistant code: - - [Github](https://guides.github.com/activities/hello-world/) - - [Pip and Virtual Environments](https://www.dabapps.com/blog/introduction-to-pip-and-virtualenv-python/) - - [Python 3](https://www.python.org/) - - [Pylint](https://www.pylint.org) - - [Flake8](http://flake8.pycqa.org/en/latest/) - - [Tox](http://tox.readthedocs.org/en/latest/) - - [TravisCl](https://travis-ci.org/) - -When contributing 3rd Party code to be used by Home Assistant: - - [Publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) diff --git a/website/versioned_docs/version-0.72/development_submitting.md b/website/versioned_docs/version-0.72/development_submitting.md deleted file mode 100644 index f67fb40f..00000000 --- a/website/versioned_docs/version-0.72/development_submitting.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Submit your work -id: version-0.72-development_submitting -original_id: development_submitting ---- - -Submit your improvements, fixes, and new features to Home Assistant one at a time, using GitHub [Pull Requests](https://help.github.com/articles/using-pull-requests). Here are the steps: - - 1. From your fork's dev branch, create a new branch to hold your changes: - - `git checkout -b some-feature` - - 2. Make your changes, create a [new platform](creating_platform_index.md), develop a [new component](creating_component_index.md), or fix [issues](https://github.com/home-assistant/home-assistant/issues). - - 3. [Test your changes](development_testing.md) and check for style violations. - - 4. If everything looks good according to these [musts](development_checklist.md), commit your changes: - - `git add .` - - `git commit -m "Added some-feature"` - - * Write a meaningful commit message and not only `Update` or `Fix`. - * Use a capital letter to start with your commit message. - * Don't prefix your commit message with `[bla.bla]` or `platform:`. - * Consider adding tests to ensure that your code works. - - 5. Push your committed changes back to your fork on GitHub: - - `git push origin HEAD` - - 6. Follow [these steps](https://help.github.com/articles/creating-a-pull-request/) to create your pull request. - - * On GitHub, navigate to the main page of the Home Assistant repository. - * In the "Branch" menu, choose the branch that contains your commits (from your fork). - * To the right of the Branch menu, click **New pull request**. - * Use the base branch dropdown menu to select the branch you'd like to merge your changes into, then use the compare branch drop-down menu to choose the topic branch you made your changes in. Make sure the Home Assistant branch matches with your forked branch (`dev`) else you will propose ALL commits between branches. - * Type a title and complete the provided description for your pull request. - * Click **Create pull request**. - - 7. Check for comments and suggestions on your pull request and keep an eye on the [CI output](https://travis-ci.org/home-assistant/home-assistant/). - diff --git a/website/versioned_docs/version-0.72/development_testing.md b/website/versioned_docs/version-0.72/development_testing.md deleted file mode 100644 index ba5062cf..00000000 --- a/website/versioned_docs/version-0.72/development_testing.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: Testing your code -id: version-0.72-development_testing -original_id: development_testing ---- - -As states in the [Style guidelines section](development_guidelines.md) all code is checked to verify all unit tests pass and that the code passes the linting tools. Local testing is done using Tox, which has been installed as part of running `script/setup`. To start the tests, simply run it: - -```bash -$ tox -``` -**Important:** Run `tox` before you create your pull request to avoid annoying fixes. - -Running Tox will run unit tests against the locally available Pythons, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one tox target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py36` runs unit tests only on Python 3.6. - -Tox uses virtual environments under the hood to create isolated testing environments. The tox virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell Tox to recreate the virtual environments. - -If you are working on tests for a component or platform and you need the dependencies available inside the Tox environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments. - -### Running single tests using Tox - -You can pass arguments via Tox to py.test to be able to run single test suites or test files. Replace `py36` with the Python version that you use. - -```bash -# Stop after the first test fails -$ tox -e py36 -- tests/test_core.py -x -# Run test with specified name -$ tox -e py36 -- tests/test_core.py -k test_split_entity_id -# Fail a test after it runs for 2 seconds -$ tox -e py36 -- tests/test_core.py --timeout 2 -# Show the 10 slowest tests -$ tox -e py36 -- tests/test_core.py --duration=10 -``` - -### Testing outside of Tox - -Running tox will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without Tox, you'll need to install the test dependencies into your Python environment: - -```bash -$ pip3 install -r requirements_test_all.txt -``` - -Now that you have all test dependencies installed, you can run tests on individual files: - -```bash -$ flake8 homeassistant/core.py -$ pylint homeassistant/core.py -$ pydocstyle homeassistant/core.py -$ py.test tests/test_core.py -``` - -You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script: - -```bash -$ script/lint -``` - -### Preventing Linter Errors - -Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them! - -```bash -$ pip3 install flake8 flake8-docstrings -$ flake8 --install-hook=git -``` - -The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8. - -### Notes on PyLint and PEP8 validation - -If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member. diff --git a/website/versioned_docs/version-0.72/development_typing.md b/website/versioned_docs/version-0.72/development_typing.md deleted file mode 100644 index 3a0d5c4e..00000000 --- a/website/versioned_docs/version-0.72/development_typing.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: Adding type hints to your code -id: version-0.72-development_typing -original_id: development_typing ---- - -Type hints in Python are static annotations of variables and functions, to let humans more easily understand the code. See the standard library [docs](https://docs.python.org/3/library/typing.html) and this PyCascades 2018 [talk](https://youtu.be/zKre4DKAB30). - -Type hints are not required for all modules at the moment in Home Assistant, but we aim to have complete coverage of the core modules. - -Adding type hints to an existing codebase can be a daunting task. To speed this up and help developers doing this, Instagram made the [`monkeytype`](https://pypi.org/project/MonkeyType/) program. It will analyze calls during runtime and try to assign the correct type hints to the code. - -See [this instagram blog post](https://instagram-engineering.com/let-your-code-type-hint-itself-introducing-open-source-monkeytype-a855c7284881) for a description of the workflow involved to use the monkeytype program. - -We've added a script to start a run of our test suite or a test module and tell the `monkeytype` program to analyze the run. - -### Basic workflow -1. Run `script/monkeytype tests/path/to/your_test_module.py`. -2. Run `monkeytype stub homeassistant.your_actual_module`. -3. Look at output from the monkeytyped typing stub. If not totally bad, apply the stub to your module. You most likely will need to manually edit the typing in the last step. -4. Run `monkeytype apply homeassistant.your_actual_module`. -5. Check the diff and manually correct the typing if needed. Commit, push the branch and make a PR. - -**Note:** -Applying a monkeytyped stub to a module that has existing typing annotations might error and not work. This tool is most useful for totally untyped modules. diff --git a/website/versioned_docs/version-0.72/development_validation.md b/website/versioned_docs/version-0.72/development_validation.md deleted file mode 100644 index 2439fddf..00000000 --- a/website/versioned_docs/version-0.72/development_validation.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: Validate the input -id: version-0.72-development_validation -original_id: development_validation ---- - -The `configuration.yaml` file contains the configuration options for components and platforms. We use [voluptuous](https://pypi.python.org/pypi/voluptuous) to make sure that the configuration provided by the user is valid. Some entries are optional or could be required to set up a platform or a component. Others must be a defined type or from an already-defined list. - -We test the configuration to ensure that users have a great experience and minimize notifications if something is wrong with a platform or component setup before Home Assistant runs. - -Besides [voluptuous](https://pypi.python.org/pypi/voluptuous) default types, many custom types are available. For an overview, take a look at the [config_validation.py](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/config_validation.py) helper. - -- Types: `string`, `byte`, and `boolean` -- Entity ID: `entity_id` and `entity_ids` -- Numbers: `small_float` and `positive_int` -- Time: `time`, `time_zone` -- Misc: `template`, `slug`, `temperature_unit`, `latitude`, `longitude`, `isfile`, `sun_event`, `ensure_list`, `port`, `url`, and `icon` - -To validate platforms using [MQTT](https://www.home-assistant.io/components/mqtt/), `valid_subscribe_topic` and `valid_publish_topic` are available. - -Some things to keep in mind: - -- Use the constants defined in `const.py` -- Import `PLATFORM_SCHEMA` from the parent component and extend it -- Preferred order is `required` first and `optional` second -- Starting with Home Assistant 0.64 `voluptuous` requires default values for optional configuration keys to be valid values. Don't use a default which is `None` like `vol.Optional(CONF_SOMETHING, default=None): cv.string`, set the default to `default=""` if required. - -### Snippets - -This section contains snippets for the validation we use. - -#### Default name - -It's common to set a default for a sensor if the user doesn't provide a name to use. - -```python -DEFAULT_NAME = 'Sensor name' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, -``` - -#### Limit the values - -You might want to limit the user's input to a couple of options. - -```python -DEFAULT_METHOD = 'GET' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): vol.In(['POST', 'GET']), -``` - -#### Port - -All port numbers are from a range of 1 to 65535. - -```python -DEFAULT_PORT = 993 - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, -``` - -#### Lists - -If a sensor has a pre-defined list of available options, test to make sure the configuration entry matches the list. - -```python -SENSOR_TYPES = { - 'article_cache': ('Article Cache', 'MB'), - 'average_download_rate': ('Average Speed', 'MB/s'), -} - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_MONITORED_VARIABLES, default=[]): - vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), -``` diff --git a/website/versioned_docs/version-0.72/entity_alarm_control_panel.md b/website/versioned_docs/version-0.72/entity_alarm_control_panel.md deleted file mode 100644 index 87f4e7dc..00000000 --- a/website/versioned_docs/version-0.72/entity_alarm_control_panel.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Alarm Control Panel Entity -sidebar_label: Alarm Control Panel -id: version-0.72-entity_alarm_control_panel -original_id: entity_alarm_control_panel ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| code_format | string | `None` | The format of the panel code. - -### Available code formats - -| Value | Description -| ----- | ----------- -| None | No code required. -| Number | Code is a number (Shows ten-key pad on frontend). -| Any | Code is a string. - -## Methods - diff --git a/website/versioned_docs/version-0.72/entity_binary_sensor.md b/website/versioned_docs/version-0.72/entity_binary_sensor.md deleted file mode 100644 index 340dbae1..00000000 --- a/website/versioned_docs/version-0.72/entity_binary_sensor.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Binary Sensor Entity -sidebar_label: Binary Sensor -id: version-0.72-entity_binary_sensor -original_id: entity_binary_sensor ---- - -A binary sensor is a sensor that can only have two states. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| is_on| boolean | **Required** | If the binary sensor is currently on or off. -| device_class | string | `None` | Type of binary sensor. - -### Available device classes - -| Value | Description -| ----- | ----------- -| battery | On means low, Off means normal. -| cold | On means cold, Off means normal. -| connectivity | On means connected, Off means disconnected. -| door | On means open, Off means closed. -| garage_door | On means open, Off means closed. -| gas | On means gas detected, Off means no gas (clear). -| heat | On means hot, Off means normal. -| light | On means light detected, Off means no light. -| lock | On means open (unlocked), Off means closed (locked). -| moisture | On means wet, Off means dry. -| motion | On means motion detected, Off means no motion (clear). -| moving | On means moving, Off means not moving (stopped). -| occupancy | On means occupied, Off means not occupied (clear). -| opening | On means open, Off means closed. -| plug | On means plugged in, Off means unplugged. -| power | On means power detected, Off means no power. -| presence | On means home, Off means away. -| problem | On means problem detected, Off means no problem (OK). -| safety | On means unsafe, Off means safe. -| smoke | On means smoke detected, Off means no smoke (clear). -| sound | On means sound detected, Off means no sound (clear). -| vibration | On means vibration detected, Off means no vibration. -| window | On means open, Off means closed. diff --git a/website/versioned_docs/version-0.72/entity_climate.md b/website/versioned_docs/version-0.72/entity_climate.md deleted file mode 100644 index 88d3d9c9..00000000 --- a/website/versioned_docs/version-0.72/entity_climate.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Climate Entity -sidebar_label: Climate -id: version-0.72-entity_climate -original_id: entity_climate ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- - -## Methods - diff --git a/website/versioned_docs/version-0.72/entity_cover.md b/website/versioned_docs/version-0.72/entity_cover.md deleted file mode 100644 index ae2bc48b..00000000 --- a/website/versioned_docs/version-0.72/entity_cover.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Cover Entity -sidebar_label: Cover -id: version-0.72-entity_cover -original_id: entity_cover ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- - -## Methods - diff --git a/website/versioned_docs/version-0.72/entity_fan.md b/website/versioned_docs/version-0.72/entity_fan.md deleted file mode 100644 index 74e5d70a..00000000 --- a/website/versioned_docs/version-0.72/entity_fan.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Fan Entity -sidebar_label: Fan -id: version-0.72-entity_fan -original_id: entity_fan ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- - -## Methods - diff --git a/website/versioned_docs/version-0.72/entity_index.md b/website/versioned_docs/version-0.72/entity_index.md deleted file mode 100644 index 61bb1147..00000000 --- a/website/versioned_docs/version-0.72/entity_index.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Entity -sidebar_label: Introduction -id: version-0.72-entity_index -original_id: entity_index ---- - -Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating. - -Below is an example switch entity that keeps track of their state in memory. - -```python -from homeassistant.components.switch import SwitchDevice - -class MySwitch(SwitchDevice): - - def __init__(self): - self._is_on = False - - @property - def name(self): - """Name of the device.""" - return 'My Switch' - - @property - def is_on(self): - """If the switch is currently on or off.""" - return self._is_on - - def turn_on(self, **kwargs): - """Turn the switch on.""" - self._is_on = True - - def turn_off(self, **kwargs): - """Turn the switch off.""" - self._is_on = False -``` - -That's all there is to it to build a switch entity! Continue reading to learn more or check out the [video tutorial](https://youtu.be/Cfasc9EgbMU?t=737). - -## Updating the entity - -An entity represents a device. There are various strategies to keep your entity in sync with the state of the device, the most popular one being polling. - -### Polling - -With polling, Home Assistant will ask the entity from time to time (depending on the update interval of the component) to fetch the latest state. Home Assistant will poll an entity when the `should_poll` property returns `True` (the default value). You can either implement your update logic using `update()` or the async method `async_update()`. This method should fetch the latest state from the device and store it in an instance variable for the properties to return it. - -### Subscribing to updates - -When you subscribe to updates, your code is responsible for letting Home Assistant know that an update is available. Make sure you have the `should_poll` property return `False`. - -Whenever you receive new state from your subscription, you can tell Home Assistant that an update is available by calling `schedule_update_ha_state()` or async callback `async_schedule_update_ha_state()`. Pass in the boolean `True` to the method if you want Home Assistant to call your update method before writing the update to Home Assistant. - -## Generic properties - -The entity base class has a few properties that are common among all entities in Home Assistant. These can be added to any entity regardless of the type. All these properties are optional and don't need to be implemented. - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| assumed_state | boolean | `False` | Return `True` if the state is based on our assumption instead of reading it from the device. -| available | boolean | `True` | Indiciate if Home Assistant is able to read the state and control the underlying device. -| device_state_attributes | dict | `None` | Extra information to store in the state machine. It needs to be information that further explains the state, it should not be static information like firmware version. See [below](entity_index.md#standard_attributes) for details of standard attributes. -| entity_picture | URL | `None` | Url of a picture to show for the entity. -| name | string | `None` | Name of the entity -| should_poll | boolean | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](#methods). -| unique_id | string | `None` | A unique identifier for this entity. Needs to be unique within a platform (ie `light.hue`). Should not be configurable by the user or be changeable. [Learn more.](entity_registry_index.md#unique-id-requirements) - -## Advanced properties - -The following properties are also available on entities. However, they are for advanced use only and should be used with caution. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| force_update | boolean | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine. -| hidden | boolean | `False` | Indicate if the entity should not be shown on the frontend. -| icon | icon | `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all devices. - -## Standard attributes - -The following `device_state_attributes` are considered standard and should follow the convention below. The constant should be imported from `homeassistant/const.py`. - -| Name | Type | Unit | Constant | Description -| ---- | ---- | ---- | -------- | ----------- -| battery_charging | boolean | N/A | `ATTR_BATTERY_CHARGING` | Battery charging status of the entity, shown as a boolean `true` or `false`. If charging is not supported, then this attribute should not be created. -| battery_level | integer | % | `ATTR_BATTERY_LEVEL` | Battery level of the entity, shown as an integer percentage between 0-100. - -## Lifecycle hooks - -Use these lifecycle hooks to execute code when certain events happen to the entity. All lifecycle hooks are async methods. - -### `async_added_to_hass()` - -Called when an entity has their entity_id and hass object assigned, before it is written to the state machine for the first time. Example uses: restore the state or subscribe to updates. - -### `async_will_remove_from_hass()` - -Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates. - -## Changing the entity model - -If you want to add a new feature to an entity or any of its subtypes (light, switch, etc), you will need to propose it first in our [architecture repo](https://github.com/home-assistant/architecture/issues). Only additions will be considered that are common features among various vendors. diff --git a/website/versioned_docs/version-0.72/entity_light.md b/website/versioned_docs/version-0.72/entity_light.md deleted file mode 100644 index a5a12316..00000000 --- a/website/versioned_docs/version-0.72/entity_light.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Light Entity -sidebar_label: Light -id: version-0.72-entity_light -original_id: entity_light ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- - -## Methods - diff --git a/website/versioned_docs/version-0.72/entity_lock.md b/website/versioned_docs/version-0.72/entity_lock.md deleted file mode 100644 index b8ac20e5..00000000 --- a/website/versioned_docs/version-0.72/entity_lock.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Lock Entity -sidebar_label: Lock -id: version-0.72-entity_lock -original_id: entity_lock ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- - -## Methods - diff --git a/website/versioned_docs/version-0.72/entity_media_player.md b/website/versioned_docs/version-0.72/entity_media_player.md deleted file mode 100644 index a92d78b6..00000000 --- a/website/versioned_docs/version-0.72/entity_media_player.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Media Player Entity -sidebar_label: Media Player -id: version-0.72-entity_media_player -original_id: entity_media_player ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| sound_mode | string | None | The current sound mode of the media player -| sound_mode_list | list | None | Dynamic list of available sound modes (set by platform, empty means sound mode not supported) - - -## Methods -### Select sound mode -Optional. Switch the sound mode of the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - def async_select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" diff --git a/website/versioned_docs/version-0.72/entity_registry_index.md b/website/versioned_docs/version-0.72/entity_registry_index.md deleted file mode 100644 index 26dde3a6..00000000 --- a/website/versioned_docs/version-0.72/entity_registry_index.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Entity Registry -sidebar_label: Introduction -id: version-0.72-entity_registry_index -original_id: entity_registry_index ---- - -The entity registry is a registry where Home Assistant keeps track of entities. Any entity that is added to Home Assistant and has a unique ID will be registered in the registry. - -Being registered has the advantage that the same entity will always get the same entity ID. It will also prevent other entities from using that entity ID. - -A user is also able to override the name of an entity in the entity registry. When set, the name of the entity registry is used in favor of the name the device might give itself. - -## Unique ID requirements - -An entity is looked up in the registry based on a combination of domain (ie `light`), platform name (ie `hue`) and the unique ID of the entity. It is therefore very important that the unique ID is unique! It is also important that it is not possible for the user to change the unique ID, because that means it will lose all its settings related to it. - -Good sources for a unique ID: - - - Serial number of a device - - MAC address of a device - - latitude/longitude - -If a device has a single serial but provides multiple entities, combine the serial with unique identifiers for the entities. For example, if a device measures both temperature and humidithy, you can uniqueley identify the entities using `{serial}-{sensor_type}`. diff --git a/website/versioned_docs/version-0.72/entity_remote.md b/website/versioned_docs/version-0.72/entity_remote.md deleted file mode 100644 index 963333da..00000000 --- a/website/versioned_docs/version-0.72/entity_remote.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Remote Entity -sidebar_label: Remote -id: version-0.72-entity_remote -original_id: entity_remote ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- - -## Methods - diff --git a/website/versioned_docs/version-0.72/entity_sensor.md b/website/versioned_docs/version-0.72/entity_sensor.md deleted file mode 100644 index 133bbbe6..00000000 --- a/website/versioned_docs/version-0.72/entity_sensor.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Sensor Entity -sidebar_label: Sensor -id: version-0.72-entity_sensor -original_id: entity_sensor ---- - -A sensor is a read-only entity that provides some information. Information has a value and optionally, a unit of measurement. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| state | string | **Required** | The value of the sensor. -| unit_of_measurement | string | `None` | The unit of measurement that the sensor is expressed in. -| device_class | string | `None` | Type of sensor. - -### Available device classes - -If specifying a device class, your sensor entity will need to also return the correct unit of measurement. - -| Type | Unit | Description -| ---- | ---- | ----------- -| battery | % | % of battery that is left. -| humidity | % | % of humidity in the air. -| illuminance | lx/lm | Light level. -| temperature | C/F | Temperature. diff --git a/website/versioned_docs/version-0.72/entity_switch.md b/website/versioned_docs/version-0.72/entity_switch.md deleted file mode 100644 index 89d0573c..00000000 --- a/website/versioned_docs/version-0.72/entity_switch.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Switch Entity -sidebar_label: Switch -id: version-0.72-entity_switch -original_id: entity_switch ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| is_on | boolean | **Required** | If the switch is currently on or off. -| current_power_w | float | `None` | The current power usage in W. -| today_energy_kwh | float | `None` | Total energy usage in kWh. -| is_standby | boolean | `None` | Indicate if the device connected to the switch is currently in standby. - -## Methods - -### Turn On - -Turn the switch on. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def turn_on(self, **kwargs) -> None: - """Turn the entity on.""" - - async def async_turn_on(self, **kwargs): - """Turn the entity on.""" - -``` - -### Turn Off - -Turn the switch off. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def turn_off(self, **kwargs): - """Turn the entity off.""" - - async def async_turn_off(self, **kwargs): - """Turn the entity off.""" -``` - -### Toggle - -Optional. If not implemented will default to checking what method to call using the `is_on` property. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def toggle(self, **kwargs): - """Toggle the entity.""" - - async def async_toggle(self, **kwargs): - """Toggle the entity.""" -``` diff --git a/website/versioned_docs/version-0.72/entity_vacuum.md b/website/versioned_docs/version-0.72/entity_vacuum.md deleted file mode 100644 index a82e7397..00000000 --- a/website/versioned_docs/version-0.72/entity_vacuum.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Vacuum Entity -sidebar_label: Vacuum -id: version-0.72-entity_vacuum -original_id: entity_vacuum ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- - -## Methods - diff --git a/website/versioned_docs/version-0.72/entity_weather.md b/website/versioned_docs/version-0.72/entity_weather.md deleted file mode 100644 index 20e1cb3b..00000000 --- a/website/versioned_docs/version-0.72/entity_weather.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Weather Entity -sidebar_label: Weather -id: version-0.72-entity_weather -original_id: entity_weather ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| state | string | **Required** | The current weather condition. -| temperature | float | **Required** | The current temperature in °C or °F. -| pressure | float | `None` | The current air pressure in hPa or inHg. -| humidity | float | `None` | The current humidity in %. -| visibility | float | `None` | The current visibility in km or mi. -| wind_speed | float | `None` | The current wind speed in km/h or mi/h. -| wind_bearing | string | `None` | The current wind bearing, 1-3 letters. -| forecast | array | `None` | Daily or Hourly forecast data. -| attribution | string | `None` | The branding text required by the API provider. - -Properties have to follow the units defined in the `unit_system`. - -### Forecast - -Forecast data should either be daily or hourly. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| datetime | string | **Required** | UTC Date time in RFC 3339 format. -| temperature | float | **Required** | The higher temperature in °C or °F -| condition | string | `None` | The weather condition at this point. -| templow | float | `None` | The lower daily Temperature in °C or °F - -### Recommended values for state and condition - -These weather conditions are included in our translation files and also show the corresponding icon. - -| Condition | Description -| --------- | ----------- -| clear-night | Clear night -| cloudy | Many clouds -| fog | Fog -| lightning | Lightning/ thunderstorms -| lightning-rainy | Lightning/ thunderstorms and rain -| partlycloudy | A few clouds -| pouring | Pouring rain -| rainy | Rain -| snowy | Snow -| snowy-rainy | Snow and Rain -| sunny | Sunshine -| windy | Wind -| windy-variant | Wind and clouds - -This means that the `weather` platforms don't need to support languages. diff --git a/website/versioned_docs/version-0.72/external_api_rest.md b/website/versioned_docs/version-0.72/external_api_rest.md deleted file mode 100644 index b0422f6f..00000000 --- a/website/versioned_docs/version-0.72/external_api_rest.md +++ /dev/null @@ -1,517 +0,0 @@ ---- -title: REST API -id: version-0.72-external_api_rest -original_id: external_api_rest ---- - -Home Assistant runs a web server accessible on port 8123. - -* http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -* http://IP_ADDRESS:8123/api/ is a Rest API. - -The API accepts and returns only JSON encoded objects. All API calls have to be accompanied by the header `X-HA-Access: YOUR_PASSWORD` (YOUR_PASSWORD as specified in your `configuration.yaml` file in the [`http:` section](https://www.home-assistant.io/components/http/)). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```bash -curl -X GET \ - -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. = - -```python -from requests import get - -url = 'http://localhost:8123/ENDPOINT' -headers = {'x-ha-access': 'YOUR_PASSWORD', - 'content-type': 'application/json'} - -response = get(url, headers=headers) -print(response.text) -``` - -> You can append `?api_password=YOUR_PASSWORD` to any URL to log in automatically. - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on a single entity -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates the current state of an entity. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```bash -$ curl -X POST -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance.
- -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` diff --git a/website/versioned_docs/version-0.72/external_api_rest_python.md b/website/versioned_docs/version-0.72/external_api_rest_python.md deleted file mode 100644 index 7a413ce2..00000000 --- a/website/versioned_docs/version-0.72/external_api_rest_python.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: REST API - Python bindings -id: version-0.72-external_api_rest_python -original_id: external_api_rest_python ---- - -See the [developer documentation][devdocs] for a full overview of the documentation. The rest of this page will contain examples on how to use it. - -[devdocs]: https://dev-docs.home-assistant.io/en/master/api/homeassistant.html#module-homeassistant.remote - -In the package [`homeassistant.remote`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/remote.py) a Python API on top of the [HTTP API](https://www.home-assistant.io/developers/api/) can be found. If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file to use the Python Remote API. - -A simple way to get all current entities is to visit the "Set State" page in the "Developer Tools". For the examples below just choose one from the available entries. Here the sensor `sensor.office_temperature` and the switch `switch.livingroom_pin_2` are used. - -First import the module and setup the basics: - -```python -import homeassistant.remote as remote - -api = remote.API('127.0.0.1', 'password') -print(remote.validate_api(api)) -``` - -### Get configuration - -Get the current configuration of a Home Assistant instance: - -```python -import homeassistant.remote as remote - -api = remote.API('127.0.0.1', 'password') - -print(remote.get_config(api)) -``` - -### Get details about services, events, and entitites - -The output from this is similar to the output you'd find via the frontend, using the [Developer Tools](https://www.home-assistant.io/docs/tools/dev-tools/). - -```python -import homeassistant.remote as remote - -api = remote.API('127.0.0.1', 'YOUR_PASSWORD') - -print('-- Available services:') -services = remote.get_services(api) -for service in services: - print(service['services']) - -print('\n-- Available events:') -events = remote.get_event_listeners(api) -for event in events: - print(event) - -print('\n-- Available entities:') -entities = remote.get_states(api) -for entity in entities: - print(entity) -``` - -### Get the state of an entity - -To get the details of a single entity, use `get_state`: - -```python -import homeassistant.remote as remote - -api = remote.API('127.0.0.1', 'YOUR_PASSWORD') -office_temp = remote.get_state(api, 'sensor.office_temperature') -print('{} is {} {}.'.format( - office_temp.name, office_temp.state, - office_temp.attributes['unit_of_measurement']) -) -``` - -This outputs the details which are stored for this entity, ie: - -```bash -Office Temperature is 19 °C. -``` - -Switches work the same way. The only difference is that both entities have different attributes. - -```python -import homeassistant.remote as remote - -api = remote.API('127.0.0.1', 'YOUR_PASSWORD') -switch_livingroom = remote.get_state(api, 'switch.livingroom_pin_2') -print('{} is {}.'.format( - switch_livingroom.name, switch_livingroom.state) -) -``` - -### Set the state of an entity - -Of course, it's possible to set the state as well: - -```python -import homeassistant.remote as remote -from homeassistant.const import STATE_ON - -api = remote.API('127.0.0.1', 'YOUR_PASSWORD') -remote.set_state(api, 'sensor.office_temperature', new_state=123) -remote.set_state(api, 'switch.livingroom_pin_2', new_state=STATE_ON) -``` - -The state will be set to the new values until the next update occurs. - -### Blinking all entities of a domain - -If you want to turn on all entities of a domain, retrieve the service via `get_services` and act on that: - - -```python -import time -import homeassistant.remote as remote - -api = remote.API('127.0.0.1', 'YOUR_PASSWORD') -domain = 'switch' - -remote.call_service(api, domain, 'turn_on') -time.sleep(10) -remote.call_service(api, domain, 'turn_off') -``` - -### Control a single entity - -To turn on or off a single switch, pass the ID of the entity: - -```python -import time -import homeassistant.remote as remote - -api = remote.API('127.0.0.1', 'YOUR_PASSWORD') -domain = 'switch' -switch_name = 'switch.livingroom_pin_2' - -remote.call_service(api, domain, 'turn_on', {'entity_id': '{}'.format(switch_name)}) -time.sleep(5) -remote.call_service(api, domain, 'turn_off', {'entity_id': '{}'.format(switch_name)}) -``` - -### Specify a timeout - -The default timeout for an API call with `call_service` is 5 seconds. Services -taking longer than this to return will raise -`homeassistant.exceptions.HomeAssistantError: Timeout`, unless provided with a -longer timeout. - -```python -import homeassistant.remote as remote - -api = remote.API('host', 'password') -domain = 'switch' - -# Assuming switch.timeout_switch takes 10 seconds to return -switch_name = 'switch.timeout_switch' - -# Raises homeassistant.exceptions.HomeAssistantError: Timeout when talking to -remote.call_service(api, domain, 'turn_on', {'entity_id': switch_name}) - -# Runs withous exception -remote.call_service(api, domain, 'turn_on', {'entity_id': switch_name}, - timeout=11) -``` - -### Send a notification - -The example uses the Jabber notification platform to send a single message to the given recipient in the `configuration.yaml` file: - -```python -import homeassistant.remote as remote - -api = remote.API('127.0.0.1', 'YOUR_PASSWORD') -domain = 'notify' -data = {"title":"Test", "message":"A simple test message from HA."} - -remote.call_service(api, domain, 'jabber', data) -``` - -## Examples - -This section contains a couple of sample scripts. - -### List all sensors and their value - -If you want to see, export or list all sensor states then an easy way to do it, is to get all entities and filter for the one you are looking for. - -```python -import homeassistant.remote as remote - -api = remote.API('127.0.0.1', 'YOUR_PASSWORD') -entities = remote.get_states(api) -for entity in entities: - if entity.entity_id.startswith('sensor'): - data = remote.get_state(api, entity.entity_id) - print('{}: {}'.format(data.attributes['friendly_name'], data.state)) -``` - -### Show difference between `last_changed` and `last_updated` - -The documentation about the [State Objects](https://www.home-assistant.io/docs/configuration/state_object/) describes the -`last_changed` and `last_updated` fields. This example shows how it works in practice. - -```python -import time - -from prettytable import PrettyTable -import homeassistant.remote as remote - -api = remote.API('127.0.0.1', 'YOUR_PASSWORD') - -ACTIONS = { - 'Create sensor': [21, 'Test'], - 'No new sensor value': [21, 'Test'], - 'New sensor value': [22, 'Test'], - 'Update attribute': [22, 'Test1'], -} - -output = PrettyTable(['Action', 'Last changed', 'Last updated']) - -for key, value in ACTIONS.items(): - remote.set_state(api, 'sensor.test', new_state=value[0], - attributes={'friendly_name': value[1]}) - data = remote.get_state(api, 'sensor.test') - output.add_row([key, data.last_changed, data.last_updated]) - time.sleep(2) - -print(output) -``` - diff --git a/website/versioned_docs/version-0.72/external_api_server_sent_events.md b/website/versioned_docs/version-0.72/external_api_server_sent_events.md deleted file mode 100644 index 65f8bd46..00000000 --- a/website/versioned_docs/version-0.72/external_api_server_sent_events.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Server-sent events -id: version-0.72-external_api_server_sent_events -original_id: external_api_server_sent_events ---- - -The [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) feature is a one-way channel from your Home Assistant server to a client which is acting as a consumer. For a bi-directional streaming API, check out the [WebSocket API](external_api_websocket.md). - -The URI that is generating the data is `/api/stream`. - -A requirement on the client-side is existing support for the [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) interface. - -There are various ways to access the stream. If you have not set an `api_password` in the [`http`](https://www.home-assistant.io/components/http/) section of your `configuration.yaml` file then you use your modern browser to read the messages. A command-line option is `curl`: - -```bash -$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \ - -H "Content-Type: application/json" http://localhost:8123/api/stream -``` - -You can create a convenient view for this by creating an HTML file (`sse.html`) in the `www` folder of your Home Assistant configuration directory (`.homeassistant`). Paste this snippet into the file: - -```html - - - -

Getting Home Assistant server events

-
- - - -``` - -Visit [http://localhost:8123/local/sse.html](http://localhost:8123/local/sse.html) to see the stream of events. - -## Examples - -A simple way to consume server-sent events is to use a command-line http client like [httpie](https://httpie.org/). Installation info is on the site (if you use Homebrew, it's `brew install httpie`). Once installed, run this snippet from your terminal: - -```bash -$ http --stream http://localhost:8123/api/stream x-ha-access:YOUR_PASSWORD content-type:application/json -``` - -### Website - -The [home-assistant-sse](https://github.com/fabaff/home-assistant-sse) repository contains a more advanced example. - -### Python - -If you want to test the server-sent events without creating a website, the Python module [`sseclient` ](https://pypi.python.org/pypi/sseclient/) can help. To install (assuming Python and pip3 are already installed): - -```bash -$ pip3 install sseclient -``` - -A simple script to consume SSE in Python looks like this: - -```python -from sseclient import SSEClient - -messages = SSEClient('http://localhost:8123/api/stream?api_password=YOUR_PASSWORD') -for msg in messages: - print(msg) -``` diff --git a/website/versioned_docs/version-0.72/external_api_websocket.md b/website/versioned_docs/version-0.72/external_api_websocket.md deleted file mode 100644 index 5b980e14..00000000 --- a/website/versioned_docs/version-0.72/external_api_websocket.md +++ /dev/null @@ -1,418 +0,0 @@ ---- -title: WebSocket API -id: version-0.72-external_api_websocket -original_id: external_api_websocket ---- - -Home Assistant contains a WebSocket API. This API can be used to stream information from a Home Assistant instance to any client that implements WebSocket. Implementations in different languages: - -- [JavaScript](https://github.com/home-assistant/home-assistant-js-websocket) - powers the frontend -- [Python](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket-client.py) - CLI client using [`asyncws`](https://async-websockets.readthedocs.io/en/latest/) -- [JavaScript/HTML](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket.html) - WebSocket connection in your browser - -Connect your websocket implementation to `ws://localhost:8123/api/websocket`. - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`websocket_api` component](https://www.home-assistant.io/components/websocket_api/) to your `configuration.yaml` file to use the WebSocket API. - -## Server states - -1. Client connects. -1. Authentication phase starts. - - If no further authentication necessary for the user: go to 3. - - Server sends `auth_required` message. - - Client sends `auth` message. - - If `auth` message correct: go to 3. - - Server sends `auth_invalid`. Go to 6. -1. Send `auth_ok` message -1. Authentication phase ends. -1. Command phase starts. - 1. Client can send commands. - 1. Server can send results of previous commands. -1. Client or server disconnects session. - -During the command phase, the client attaches a unique identifier to each message. The server will add this identifier to each message so that the client can link each message to its origin. - -## Message format - -Each API message is a JSON serialized object containing a `type` key. After the authentication phase messages also must contain an `id`, an integer that contains the number of interactions. - -Example of an auth message: - -```json -{ - "type": "auth", - "api_password": "supersecret" -} -``` - -```json -{ - "id" 5, - "type":"event", - "event":{ - "data":{}, - "event_type":"test_event", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -## Authentication phase - -When a client connects to the server, the server will test if the client is authenticated. Authentication will not be necessary if no api_password is set or if the user fulfills one of the other criteria for authentication (trusted network, password in url/header). - -If no authentication is needed, the authentication phase will complete and the server will send an `auth_ok` message. - -```json -{ - "type": "auth_ok" -} -``` - -If authentication is necessary, the server sends out `auth_required`. - -```json -{ - "type": "auth_required" -} -``` - -This means that the next message from the client should be an auth message. You can authorize with either an API password (legacy auth) or an access token. - -```json -{ - "type": "auth", - "api_password": "supersecret" -} -``` - -or - -```json -{ - "type": "auth", - "access_token": "ABCDEFGH" -} -``` - - -If the client supplies valid authentication, the authentication phase will complete by the server sending the `auth_ok` message: - -```json -{ - "type": "auth_ok" -} -``` - -If the data is incorrect, the server will reply with `auth_invalid` message and disconnect the session. - -```json -{ - "type": "auth_invalid", - "message": "Invalid password" -} -``` - -## Command phase - -During this phase the client can give commands to the server. The server will respond to each command with a `result` message indicating when the command is done and if it was successful. - -```json -{ - "id": 6. - "type": "result", - "success": true, - // Can contain extra result info - "result": null -} -``` - -## Subscribe to events - -The command `subscribe_events` will subscribe your client to the event bus. You can either listen to all events or to a specific event type. If you want to listen to multiple event types, you will have to send multiple `subscribe_events` commands. - -```json -{ - "id": 18, - "type": "subscribe_events", - // Optional - "event_type": "state_changed" -} -``` - -The server will respond with a result message to indicate that the subscription is active. - -```json -{ - "id": 18, - "type": "result", - "success": true, - "result": null -} -``` - -For each event that matches, the server will send a message of type `event`. The `id` in the message will point at the original `id` of the `listen_event` command. - -```json -{ - "id": 18, - "type":"event", - "event":{ - "data":{ - "entity_id":"light.bed_light", - "new_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:24.265390+00:00", - "state":"on", - "attributes":{ - "rgb_color":[ - 254, - 208, - 0 - ], - "color_temp":380, - "supported_features":147, - "xy_color":[ - 0.5, - 0.5 - ], - "brightness":180, - "white_value":200, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:24.265390+00:00" - }, - "old_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:10.466994+00:00", - "state":"off", - "attributes":{ - "supported_features":147, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:10.466994+00:00" - } - }, - "event_type":"state_changed", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -### Unsubscribing from events - -You can unsubscribe from previously created subscription events. Pass the id of the original subscription command as value to the subscription field. - -```json -{ - "id": 19, - "type": "unsubscribe_events", - "subscription": 18 -} -``` - -The server will respond with a result message to indicate that unsubscribing was successful. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": null -} -``` - -### Calling a service - -This will call a service in Home Assistant. Right now there is no return value. The client can listen to `state_changed` events if it is interested in changed entities as a result of a service call. - -```json -{ - "id": 24, - "type": "call_service", - "domain": "light", - "service": "turn_on", - // Optional - "service_data": { - "entity_id": "light.kitchen" - } -} -``` - -The server will indicate with a message indicating that the service is done executing. - -```json -{ - "id": 24, - "type": "result", - "success": true, - "result": null -} -``` - -### Fetching states - -This will get a dump of all the current states in Home Assistant. - -```json -{ - "id": 19, - "type": "get_states" -} -``` - -The server will respond with a result message containing the states. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -### Fetching config - -This will get a dump of the current config in Home Assistant. - -```json -{ - "id": 19, - "type": "get_config" -} -``` - -The server will respond with a result message containing the config. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -### Fetching services - -This will get a dump of the current services in Home Assistant. - -```json -{ - "id": 19, - "type": "get_services" -} -``` - -The server will respond with a result message containing the services. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -### Fetching panels - -This will get a dump of the current registered panels in Home Assistant. - -```json -{ - "id": 19, - "type": "get_panels" -} -``` - -The server will respond with a result message containing the current registered panels. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -### Fetching camera thumbnails - -_Introduced in Home Assistant 0.69._ - -Return a b64 encoded thumbnail of a camera entity. - -```json -{ - "id": 19, - "type": "camera_thumbnail" -} -``` - -The server will respond with a result message containing the thumbnail. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -### Fetching media player thumbnails - -_Introduced in Home Assistant 0.69._ - -Fetch a base64 encoded thumbnail picture for a media player. - -```json -{ - "id": 19, - "type": "media_player_thumbnail", - "entity_id": "media_player.living_room" -} -``` - -The server will respond with the image encoded via base64. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Error handling - -If an error occurs, the `success` key in the `result` message will be set to `false`. It will contain an `error` key containing an object with two keys: `code` and `message`. - -| Code | Description | -| ----- | ------------ | -| 1 | A non-increasing identifier has been supplied. -| 2 | Received message is not in expected format (voluptuous validation error). -| 3 | Requested item cannot be found - -```json -{ - "id": 12, - "type":"result", - "success": false, - "error": { - "code": 2, - "message": "Message incorrectly formatted: expected str for dictionary value @ data['event_type']. Got 100" - } -} -``` diff --git a/website/versioned_docs/version-0.72/frontend_add_card.md b/website/versioned_docs/version-0.72/frontend_add_card.md deleted file mode 100644 index 23cdbf19..00000000 --- a/website/versioned_docs/version-0.72/frontend_add_card.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Adding state card -id: version-0.72-frontend_add_card -original_id: frontend_add_card ---- - -The main interface of Home Assistant is a list of the current entities and their states. For each entity in the system, a state card will be rendered. State cards will show an icon, the name of the entity, when the state has last changed and the current state or a control to interact with it. - -![Cards in the frontend](/img/en/frontend/frontend-cards1.png) - -The different card types can be found [here](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary). - -Sensors, when not grouped, are shown as so-called badges on top of the state cards. - -![Badges in the frontend](/img/en/frontend/frontend-badges.png) - -The different badges are located in the file [`/src/components/entity/ha-state-label-badge.js`](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/components/entity/ha-state-label-badge.js). - -Adding a custom card type can be done with a few simple steps. For this example we will add a new state card for the domain `camera`: - - 1. Add `'camera'` to the array `DOMAINS_WITH_CARD` in the file [/common/const.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/common/const.js). - 2. Create the files `state-card-camera.js` in the folder [/state-summary/](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary). - 3. Add `import './state-card-camera.js';` to [state-card-content.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/state-summary/state-card-content.js). diff --git a/website/versioned_docs/version-0.72/frontend_add_more_info.md b/website/versioned_docs/version-0.72/frontend_add_more_info.md deleted file mode 100644 index 74eaf390..00000000 --- a/website/versioned_docs/version-0.72/frontend_add_more_info.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Adding more info dialogs -id: version-0.72-frontend_add_more_info -original_id: frontend_add_more_info ---- - -Whenever the user taps or clicks on one of the cards, a more info dialog will show. The header of this dialog will be the state card, followed by the history of this entity for the last 24 hours. Below this the more info component is rendered for that entity. The more info component can show more information or allow more ways of control. - -The more info dialog for a light allows the user to control the color and the brightness. - -The instructions to add a more info dialog are very similar to adding a new card type. This example will add a new more info component for the domain `camera`: - - 1. Add `'camera'` to the array `DOMAINS_WITH_MORE_INFO` in the file [/common/entity/state_more_info_type.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/common/entity/state_more_info_type.js). - 2. Create the files `more-info-camera.js` in the folder [/dialogs/more-info/controls](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/dialogs/more-info/controls). - 3. Add `import './more-info-camera.js';` to [/dialogs/more-info/controls/more-info-content.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/dialogs/more-info/controls/more-info-content.js) diff --git a/website/versioned_docs/version-0.72/frontend_add_websocket_api.md b/website/versioned_docs/version-0.72/frontend_add_websocket_api.md deleted file mode 100644 index 9710f1df..00000000 --- a/website/versioned_docs/version-0.72/frontend_add_websocket_api.md +++ /dev/null @@ -1,131 +0,0 @@ ---- -title: Extending the WebSocket API -id: version-0.72-frontend_add_websocket_api -original_id: frontend_add_websocket_api ---- - -As a component you might have information that you want to make available to the frontend. For example, the media player will want to make album covers available for the frontend to show. Our frontend is communicating with the backend over the websocket API, which can be extended with custom commands. - -## Registering a command (Python) - -To register a command, you need to have a message type, a message schema and a message handler. Your component does not have to add the websocket API as a dependency. You register your command, and if the user is using the websocket API, the command will be made available. - -### Message Types - -Message types are made up the domain and the message type, separated by a forward slash. In the below example, we're defining `media_player/thumbnail`. - -```python -# The type of the message -WS_TYPE_MEDIA_PLAYER_THUMBNAIL = 'media_player/thumbnail' -``` - -### Message Schema - -The message schema defines what type of data we expect when the message is invoked. It is defined as a voluptuous schema and has to extend the base web socket command schema. - -```python -import voluptuous as vol - -from homeassistant.components import websocket_api -import homeassistant.helpers.config_validation as cv - - -# The schema for the message -SCHEMA_WEBSOCKET_GET_THUMBNAIL = \ - websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({ - 'type': WS_TYPE_MEDIA_PLAYER_THUMBNAIL, - # The entity that we want to retrieve the thumbnail for. - 'entity_id': cv.entity_id - }) -``` - -### Defining a handler - -Message handlers are callback functions that are run inside the event loop. If you want to do I/O or have to wait for your result, create a new function and queue it up using `hass.async_add_job`. This is done so that the websocket API can get back to handling the next message as soon as possible. - -#### Sending a direct response - -If you are defining a command that is querying simple information, you might be able to fulfill the request while the handler is being called by the websocket API. To do this, use `connection.to_write.put_nowait`. - -```python -@callback -def websocket_handle_thumbnail(hass, connection, msg): - """Handle getting a thumbnail.""" - - # We know the answer without having to fetch any information, - # so we send it directly. - connection.to_write.put_nowait(websocket_api.result_message(msg['id'], { - 'thumbnail': 'http://via.placeholder.com/350x150' - })) -``` - -#### Sending a delayed response - -If your command needs to interact with the network, a device or needs to compute information, you will need to queue a job to do the work and send the response. To do this, use `connection.send_message_outside`. - -```python -@callback -def websocket_handle_thumbnail(hass, connection, msg): - """Handle get media player cover command.""" - # Retrieve media player using passed in entity id. - player = hass.data[DOMAIN].get_entity(msg['entity_id']) - - # If the player does not exist, send an error message. - if player is None: - connection.to_write.put_nowait(websocket_api.error_message( - msg['id'], 'entity_not_found', 'Entity not found')) - return - - # Define a function to be enqueued. - async def send_image(): - """Send image.""" - data, content_type = await player.async_get_media_image() - - # No media player thumbnail available - if data is None: - connection.send_message_outside(websocket_api.error_message( - msg['id'], 'thumbnail_fetch_failed', - 'Failed to fetch thumbnail')) - return - - connection.send_message_outside(websocket_api.result_message( - msg['id'], { - 'content_type': content_type, - 'content': base64.b64encode(data).decode('utf-8') - })) - - # Player exist. Queue up a job to send the thumbnail. - hass.async_add_job(send_image()) -``` - -### Registering with the Websocket API - -With all pieces defined, it's time to register the command. This is done inside your setup method. - -```python -async def async_setup(hass, config): - """Setup of your component.""" - hass.components.websocket_api.async_register_command( - WS_TYPE_MEDIA_PLAYER_THUMBNAIL, websocket_handle_thumbnail, - SCHEMA_WEBSOCKET_GET_THUMBNAIL) -``` - -## Calling the command from the frontend (JavaScript) - -With your command defined, it's time to call it from the frontend! This is done using JavaScript. You will need access to the `hass` object which holds the WebSocket connection to the backend. Then just call `hass.connection.sendMessagePromise`. This will return a promise that will resolve if the command succeeds and errors if the command fails. - -```js -hass.connection.sendMessagePromise({ - type: 'media_player/thumbnail', - entity_id: 'media_player.living_room_tv', -}).then( - (resp) => { - console.log('Message success!', resp.result); - }, - (err) => { - console.error('Message failed!', err); - } -); -``` - -If your command is not sending a response, you can use `hass.connection.sendMessage`. diff --git a/website/versioned_docs/version-0.72/frontend_architecture.md b/website/versioned_docs/version-0.72/frontend_architecture.md deleted file mode 100644 index 2bd2f49c..00000000 --- a/website/versioned_docs/version-0.72/frontend_architecture.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Home Assistant Frontend Architecture -sidebar_label: Architecture -id: version-0.72-frontend_architecture -original_id: frontend_architecture ---- - -The Home Assistant frontend is built using web components. This is a modern web technology allowing us to encapsulate templates, styling and logic into a single file and expose it as an HTML tag in the browser. These componens are composable, allowing a very dynamic and powerful foundation of our application. - -## Structure - -The Home Assistant frontend can be broken up in 4 parts: - -### Bootstrap - -File: `src/entrypoints/core.js` - -This is a very tiny script which is the first thing that is loaded on the page. It is responsible for checking for authentication credentials and setting up the websocket connection with the backend. - -The script allows us to start downloading the data while also downloading the rest of the UI in parallel. - -### App shell - -File: `src/entrypoints/app.js` - -This is everything that is required to render the sidebar and handle the routing. - -### Panels - -Folder: `src/panels/` - -Each page in Home Assistant is a panel. Components can register extra panels to be shown to the user. Examples of panels are "states", "map", "logbook" and "history". - -### More info dialog - -Folder: `src/dialogs/more-info` - -This is a dialog that allows users to see more information about an entity and control it's state. - -The more info dialog can be triggered from any component in the app by firing a DOM event `hass-more-info` with as detail `{ entityId: 'light.kitchen' }`. - -## Data Flow - -The frontend leverages the [Websocket API](external_api_websocket.md) and the [Rest API](external_api_rest.md) to interact with Home Assistant. - -The data is made available as the `hass` property which is passed down to every component. The `hass` property contains the whole application state and has methods to call APIs. - -We use a unidirectional data flow (like Flux, Redux). When you make a change in the backend (like turning on a light), the `hass` object will be updated at the root of the application and will be made available to every component that needs it. - -## Routing - -The frontend uses decentralized routing. Each component only knows enough about the routing to know how to handle the part it's responsible for. Further routing is passed down the component tree. - -For example, the `` main component will look at the first part of the url to decide which panel should be loaded. Each panel can have its own mapping between the url and what content to show. - -For the routing, we use the [``](https://www.polymer-project.org/3.0/toolbox/routing) web component. - -## Bundling - -We use Webpack to bundle up the application. We have various gulp scripts to help with generating the icon set and the index.html. - -We're aggresively code splitting our application by leveraging the dynamic import syntax (`import('path/to/some/file.js')`). When encountering an `import()`, Webpack will split the code into different chunks and makes sure that they are loaded when needed. - - diff --git a/website/versioned_docs/version-0.72/frontend_creating_custom_panels.md b/website/versioned_docs/version-0.72/frontend_creating_custom_panels.md deleted file mode 100644 index ca449582..00000000 --- a/website/versioned_docs/version-0.72/frontend_creating_custom_panels.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Creating custom panels -id: version-0.72-frontend_creating_custom_panels -original_id: frontend_creating_custom_panels ---- - -Panels are pages that show information within Home Assistant and can allow controlling it. Panels are linked from the sidebar and rendered full screen. They have real-time access to the Home Assistant object via JavaScript. Examples of panels in the app are Map, Logbook and History. - -Besides components registering panels, users can also register panels using the `panel_custom` component. This allows users to quickly build their own custom interfaces for Home Assistant. - -## Before you get started - -The Home Assistant user interface is currently served to browsers in modern JavaScript and older JavaScript (ES5). The older version has a wider browser support but that comes at a cost of size, performance and more difficult to get started building panels for authors. - -We therefore advise you to set up Home Assistant to serve the modern version of the frontend so that you won't need any build tools while developing. If you realize that your audience requires both, you can add a transpilation step in the future. To set up your frontend to always serve the latest version, add this to your config: - -``` -frontend: - javascript_version: latest -``` - -## Building your first panel - -Create a file called `hello.html` in your /panels/. - -The `hello.html` contains the needed building blocks to create the elements inside the view. - -```html - - - - - -``` - -Create an entry for the new panel in your `configuration.yaml` file: - -```yaml -panel_custom: - - name: hello - sidebar_title: Hello World - sidebar_icon: mdi:hand-pointing-right - url_path: hello -``` diff --git a/website/versioned_docs/version-0.72/frontend_creating_custom_ui.md b/website/versioned_docs/version-0.72/frontend_creating_custom_ui.md deleted file mode 100644 index 4e1a0c17..00000000 --- a/website/versioned_docs/version-0.72/frontend_creating_custom_ui.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Creating custom UI -id: version-0.72-frontend_creating_custom_ui -original_id: frontend_creating_custom_ui ---- - -### State card - -If you would like to use your own [State card](frontend_add_card.md) without merging your code into [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer/) you can create your own implementation. - -Put the element source file and its dependencies in `www/custom_ui/` directory under your Home Assistant [configuration](https://www.home-assistant.io/docs/configuration/) directory. - -For example if creating a state card for the `light` domain named `state-card-my-custom-light` put `state-card-my-custom-light.html` in `www/custom_ui/`. - -That file should implement `` tag with Polymer. - -In `state-card-my-custom-light.html` you should use `` to import all the dependencies **not** used by Home Assistant's UI. -Do not import any dependencies used by the Home Assistant UI. -Importing those will work in `development: 1` mode, but will fail in production mode. - -1. In the `customize:` section of the `configuration.yaml` file put `custom_ui_state_card: state-card-my-custom-light`. -2. In the `frontend` section use `extra_html_url` to specify the URL to load. - -Example: - -`configuration.yaml`: - -```yaml -homeassistant: - customize: - light.bedroom: - custom_ui_state_card: state-card-my-custom-light - -frontend: - extra_html_url: - - /local/custom_ui/state-card-my-custom-light.html -``` - -`www/custom_ui/state-card-my-custom-light.html`: - -```html - - - - - - -``` - -> Some browsers don't support latest ECMAScript standards, these require a separate ES5 compatible file (`extra_html_url_es5`). - -For more possibilities, see the [Custom UI section](https://www.home-assistant.io/cookbook/#user-interface) on our Examples page. - -### More info dialog - -_Introduced in Home Assistant 0.69._ - -Similar to the custom State card, if you would like to use your own [More info dialog](frontend_add_more_info.md) you can create your own implementation. - -Following a similar example, if creating a more info dialog a light named `more-info-my-custom-light` put `more-info-my-custom-light.html` in `www/custom_ui/`. - -1. In the `customize:` section of the `configuration.yaml` file put `custom_ui_more_info: more-info-my-custom-light`. -2. In the `frontend` section use `extra_html_url` to specify the URL to load. - -Example: - -`configuration.yaml`: - -```yaml -homeassistant: - customize: - light.bedroom: - custom_ui_more_info: more-info-my-custom-light - -frontend: - extra_html_url: - - /local/custom_ui/more-info-my-custom-light.html -``` diff --git a/website/versioned_docs/version-0.72/frontend_development.md b/website/versioned_docs/version-0.72/frontend_development.md deleted file mode 100644 index d9e45ae3..00000000 --- a/website/versioned_docs/version-0.72/frontend_development.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Frontend development -sidebar_label: Development -id: version-0.72-frontend_development -original_id: frontend_development ---- - -The Home Assistant frontend is built using web components and powered by the [Polymer](https://www.polymer-project.org/) framework. - -> Do not use development mode in production. Home Assistant uses aggressive caching to improve the mobile experience. This is disabled during development so that you do not have to restart the server in between changes. - -## Setting up the environment - -> All commands below need to be run from inside the home-assistant-polymer repository. - -### Getting the code - -First step is to git clone the [home-assistant-polymer repository][hass-polymer]. You can place the repository anywhere on your system. - -```bash -$ git clone https://github.com/home-assistant/home-assistant-polymer.git -$ cd home-assistant-polymer -``` - -### Configuring Home Assistant - -Next step is to configure Home Assistant to use the development mode for the frontend. Do this by updating the frontend config in your `configuration.yaml` and set the path to the home-assistant-polymer repository that you cloned in the last step: - -```yaml -frontend: - # Example absolute path: /home/paulus/dev/hass/home-assistant-polymer - development_repo: -``` - -### Installing Node.js - -Node.js is required to build the frontend. The preferred method of installing node.js is with [nvm](https://github.com/creationix/nvm). Install nvm using the instructions in the [README](https://github.com/creationix/nvm#install-script), and install the correct node.js by running the following command: - -```bash -$ nvm install -``` - -[Yarn](https://yarnpkg.com/en/) is used as the package manager for node modules. [Install yarn using the instructions here.](https://yarnpkg.com/en/docs/install) - -Next, development dependencies need to be installed to bootstrap the frontend development environment. First activate the right Node version and then download all the dependencies: - -```bash -$ nvm use -$ script/bootstrap -``` - -## Development - -During development, you will need to run the development script to maintain a development build of the frontend that auto updates when you change any of the source files. To run this server, run: - -```bash -$ nvm use -$ script/develop -``` - -## Creating pull requests - -If you're planning on issuing a PR back to the Home Assistant codebase you need to fork the polymer project and add your fork as a remote to the Home Assistant Polymer repo. - -```bash -$ git remote add fork -``` - -When you've made your changes and are ready to push them change to the working directory for the polymer project and then push your changes - -``` bash -$ git add -A -$ git commit -m "Added new feature X" -$ git push -u fork HEAD -``` - -## Building the Polymer frontend - -If you're making changes to the way the frontend is packaged, it might be necessary to try out a new packaged build of the frontend in the main repository (instead of pointing it at the frontend repo). To do so, first build a production version of the frontend by running `script/build_frontend`. - -To test it out inside Home assistant, run the following command from the main Home Assistant repository: - -```bash -$ pip3 install -e /path/to/home-assistant-polymer/ -$ hass --skip-pip -``` - -[hass-polymer]: https://github.com/home-assistant/home-assistant-polymer diff --git a/website/versioned_docs/version-0.72/frontend_index.md b/website/versioned_docs/version-0.72/frontend_index.md deleted file mode 100644 index 33904d94..00000000 --- a/website/versioned_docs/version-0.72/frontend_index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Home Assistant Frontend -sidebar_label: Introduction -id: version-0.72-frontend_index -original_id: frontend_index ---- - -The Home Assistant frontend allows users to browse and control the state of their house, manage their automations and configure integrations. - -The frontend is designed as a mobile-first experience. It is a progressive web application and offers an app-like experience to our users. - -![Screenshot of the Home Assistant Frontend](/img/en/frontend/frontend-hero.png) diff --git a/website/versioned_docs/version-0.72/hassio_addon_communication.md b/website/versioned_docs/version-0.72/hassio_addon_communication.md deleted file mode 100644 index f3a3e074..00000000 --- a/website/versioned_docs/version-0.72/hassio_addon_communication.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Add-On Communication -id: version-0.72-hassio_addon_communication -original_id: hassio_addon_communication ---- - -There are different ways for communication between add-ons inside Hass.io. - -## Network - -We use an internal network that allows to communicate with every add-on, even to/from Home Assistant, by using its name or alias. Only the add-ons which run on the host network are a bit limited. These can talk with all internal add-ons by their name but all other add-on can't address these add-on by name - using an alias works for both! - -Name/alias are used for communication inside Hass.io. -The name is generated using the following format: `{REPO}_{SLUG}`, e.g., `local_xy` or `3283fh_myaddon`. In this example, `{SLUG}` is defined in an add-ons `config.json`. You can use this name also as DNS name but you need replace the `_` with `-` to have a valid hostname. If an add-on is installed locally, `{REPO}` will be `local`. If the add-on is installed from a Github repository, `{REPO}` is a hashed identifier generated from the GitHub repository's URL (ex: https://github.com/xy/my_hassio_addons). See [here](https://github.com/home-assistant/hassio/blob/587047f9d648b8491dc8eef17dc6777f81938bfd/hassio/addons/utils.py#L17) to understand how this identifier is generated. Note that this identifier is required in certain service calls that use the [Hass.io add-on API][hassio-addon-api]. You can view the repository identifiers for all currently installed add-ons via a GET request to the hassio API `addons` endpoint. - -Use `hassio` for communication with the internal API. - -## Home Assistant - -An add-on can talk to the [Home Assistant API][hass-api] using the internal proxy. That makes it very easy to communicate with the API without knowing the password, port or any other information of the Home Assistant instance. Use this URL: `http://hassio/homeassistant/api` and internal communication is redirected to the right place. The next stept is to add `homeassistant_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN` and use this as Home-Assistant password. - -There is also a proxy for the [Home Assistant Websocket API][hass-websocket]. It works like the API proxy above and requires `HASSIO_TOKEN` as password. Use this URL: `http://hassio/homeassistant/websocket`. - -It is also possible to talk direct to the Home Assistant instance which is named `homeassistant` over the internal network. But you need to know the configuration that is used by the running instance. - -We have severals services for Hass.io inside Home Assistant to run tasks. To send data over STDIN to an add-on use the `hassio.addon_stdin` service. - -## Hass.io API - -To enables calls to the [Hass.io API][hassio-api], add `hassio_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN`. Now you can use the API over the URL: `http://hassio/`. Use the `HASSIO_TOKEN` with header `X-HASSIO-KEY`. - -[hass-api]: https://www.home-assistant.io/developers/rest_api/ -[hass-websocket]: https://www.home-assistant.io/developers/websocket_api/ -[hassio-api]: https://github.com/home-assistant/hassio/blob/master/API.md -[hassio-addon-api]: https://github.com/home-assistant/hassio/blob/dev/API.md#restful-for-api-addons diff --git a/website/versioned_docs/version-0.72/hassio_addon_config.md b/website/versioned_docs/version-0.72/hassio_addon_config.md deleted file mode 100644 index 88374b56..00000000 --- a/website/versioned_docs/version-0.72/hassio_addon_config.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.72-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use `jq` inside your shell script to parse this data. However, you might have to install `jq` as a separate package in your container (see `Dockerfile` below). - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -## Add-on Docker file - -All add-ons are based on Alpine Linux 3.6. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | no | List of supported arch: `armhf`, `aarch64`, `amd64`, `i386`. Default all. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE` -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. -| devicetree | bool | no | Boolean. If this is set to True, `/sys/firmware/devicetree` will map into add-on. -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. diff --git a/website/versioned_docs/version-0.72/hassio_addon_index.md b/website/versioned_docs/version-0.72/hassio_addon_index.md deleted file mode 100644 index 302f963f..00000000 --- a/website/versioned_docs/version-0.72/hassio_addon_index.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Developing an add-on -sidebar_label: Introduction -id: version-0.72-hassio_addon_index -original_id: hassio_addon_index ---- - -Add-ons for Hass.io allow the user to extend the functionality around Home Assistant. This can be running an application that Home Assistant can integrate with (like an MQTT broker) or to share the configuration via Samba for easy editing from other computers. Add-ons can be configured via the Hass.io panel in Home Assistant. - -Under the hood, add-ons are Docker images published in [Docker Hub](https://hub.docker.com/). Developers can create [GitHub](https://github.com) repositories that contain multiple references to add-ons for easy sharing with the community. - -1. [Tutorial: Making your first add-on](hassio_addon_tutorial.md) -1. [Configuration](hassio_addon_config.md) -1. [Communication](hassio_addon_communication.md) -1. [Local Testing](hassio_addon_testing.md) -1. [Publishing](hassio_addon_publishing.md) -1. [Presentation](hassio_addon_presentation.md) -1. [Repositories](hassio_addon_repository.md) diff --git a/website/versioned_docs/version-0.72/hassio_addon_presentation.md b/website/versioned_docs/version-0.72/hassio_addon_presentation.md deleted file mode 100644 index 010942d0..00000000 --- a/website/versioned_docs/version-0.72/hassio_addon_presentation.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Presenting your add-on -id: version-0.72-hassio_addon_presentation -original_id: hassio_addon_presentation ---- - -If you decide to share your add-on to the public, paying attention to details is recommended. Of course, your add-on should have a proper name and description, but Hass.io also gives you some other tools to present your add-on even nicer. - -## Adding documentation - -Good documentation helps the consumer of your add-on to understand its usage, explains configuration options, points users in the right direction in the case they have questions or issues, and contains the license under which the add-on was published. - -This file containing the documentation is usually referred to as the "README", which is generally published as the `README.md` file. - -Take a look at other projects for inspiration. For example, see the `README.md` of the [Community Hass.io Add-ons: Homebridge](https://github.com/hassio-addons/addon-homebridge/blob/master/README.md) add-on. - -In future versions of Hass.io, the `README.md` file will be displayed in the Home Assistant frontend. - -## Add-on icon & logo - -A picture is worth a thousand words. Therefore, your add-on can be improved by adding a proper image icon and logo. Those images are used when showing your add-on in the Home Assistant Hass.io panel and which will significantly improve the visual representation of your add-on. - -Requirements for the logo of your add-on: - -- The logo must be in the Portable Network Graphics format (`.png`). -- The filename must be `logo.png`. -- It is recommended to keep the logo size around 250x100px. You may choose to use a different size or aspect ratio as you seem fit for your add-on. - -Requirements for the icon of your add-on: - -- The icon must be in the Portable Network Graphics format (`.png`). -- The filename must be `icon.png`. -- The aspect ratio of the icon must be 1x1 (square). -- It is recommended to use an icon size of 128x128px. - -## Keeping a changelog - -It is likely you are going to release newer versions of your add-on in the future. In case that happens, the users of your add-on would see an upgrade notice and probably want to know what changes were made in the latest version. - -A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of your add-on and is generally published as the `CHANGELOG.md` file. - -If you are in need of a guide on keeping a changelog, we would recommend checking the [keep a changelog](http://keepachangelog.com) website. They have developed a standard that is used by many opensource projects around the world. - -In future versions of Hass.io, the `CHANGELOG.md` file will be displayed in the Home Assistant frontend. - -## Apparmor - -You can use own security profile for you Add-on with AppArmor. Default it is enabled and use the docker default profile. Put `apparmor.txt` file into your Add-on folder and it will load this file as primary profile. Use the config options to set the name of that profile. diff --git a/website/versioned_docs/version-0.72/hassio_addon_publishing.md b/website/versioned_docs/version-0.72/hassio_addon_publishing.md deleted file mode 100644 index 62d28f34..00000000 --- a/website/versioned_docs/version-0.72/hassio_addon_publishing.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Publishing your add-on -id: version-0.72-hassio_addon_publishing -original_id: hassio_addon_publishing ---- - -There are two different ways of publishing add-ons. One is to publish pre-build containers to Docker Hub and the other option is to have users build the containers locally on their Hass.io instance. - -#### Pre-build containers - -With pre-build containers, the developer is responsible for building the images for each architecture on their machine and push the results out to Docker Hub. This has a lot of advantages for the user. As a user it will only have to download the final container and be up and running once the download finishes. This makes the installation process fast and almost no chance of failure. This is the preferred method. - -We have automated the process of building and publishing add-ons. See below for the instructions. - -#### Locally build containers - -Starting Hass.io 0.26, it is possible to distribute add-ons that will be built on the users machine. The advantage is that as a developer it is easy to test an idea and see if people are interested in your add-ons. This method includes installing and potentially compiling code. This means that installing such an add-on is slow and adds more wear and tear to users SD card/hard drive than the above mentioned pre-build solution. It also has a higher chance of failure if one of the dependencies of the container has changed or is no longer available. - -Use this option when you are playing with add-ons and seeing if someone is interested in your work. Once you're an established repository, please migrate to pushing builds to Docker Hub as it greatly improves the user experience. In the future we will mark locally built add-ons in the add-on store to warn users. - -## Build scripts to publish add-ons to Docker Hub - -All add-ons are simple docker containers. Inside your add-on `config.json` you specify the Docker image that will be installed for your add-on: - -```json -{ - ... - - "image": "myhub/image-{arch}-addon-name", - - ... -} -``` - -You can use `{arch}` inside the image name to support multiple architectures with 1 configuration file. It will be replaced with the architecture of the user when we load the image. If you use `Buildargs` you can use the `build.json` to overwrite our default args. - -Hass.io assumes that the `master` branch of your add-on repository matches the latest tag on Docker Hub. When you're building a new version, it's suggested that you use another branch, ie `build` or do it with a PR on GitHub. After you push the add-on to [Docker Hub](https://hub.docker.com/), you can merge this branch to master. - -## Custom Add-ons - -You need a Docker Hub account to make your own add-ons. You can build your docker images with docker `build` command or use our script that make it simple. Pull our [builder docker engine][builder] and run one of the following commands. - -For a git repository: - -```bash -$ docker run --rm --privileged -v ~/.docker:/root/.docker homeassistant/amd64-builder --all -t addon-folder -r https://github.com/xy/addons -b branchname -``` - -For a local repository: - -```bash -$ docker run --rm --privileged -v ~/.docker:/root/.docker -v /my_addon:/data homeassistant/amd64-builder --all -t /data -``` - -> If you are developing on macOS and using Docker for Mac, you may encounter an error message similar to the following: error creating aufs mount to /var/lib/docker/aufs/mnt/-init: invalid argument. A proposed workaround is to add the following to the Advanced Daemon JSON configuration via Docker > Preferences > Daemon > Advanced: "storage-driver" : "aufs". - -[builder]: https://github.com/home-assistant/hassio-build/tree/master/builder diff --git a/website/versioned_docs/version-0.72/hassio_addon_repository.md b/website/versioned_docs/version-0.72/hassio_addon_repository.md deleted file mode 100644 index d63235e4..00000000 --- a/website/versioned_docs/version-0.72/hassio_addon_repository.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Create an add-on repository -id: version-0.72-hassio_addon_repository -original_id: hassio_addon_repository ---- - -An add-on repository can contain one or more add-ons. Each add-on is stored in its own unique folder. To be indentified as a repository, the repository must contain a configuration file. - -Check the [Example add-on repository](https://github.com/home-assistant/hassio-addons-example) for further details. - -## Installing a repository - -A user can add a repository by going to the Hass.io panel in Home Assistant, clicking on the store icon in the top right, copy/paste the URL of your repostory into the repository textarea and click on **Save**. - -## Repository configuration - -Each repository is required to contain `repository.json` at the root in the git repository. - -```json -{ - "name": "Name of repository", - "url": "http://www.example/addons", - "maintainer": "HomeAssistant Team " -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| name | yes | Name of the repository -| url | no | Homepage of the repository. Here you can explain the various add-ons. -| maintainer | no | Contact info of the maintainer. diff --git a/website/versioned_docs/version-0.72/hassio_addon_testing.md b/website/versioned_docs/version-0.72/hassio_addon_testing.md deleted file mode 100644 index 7feccc75..00000000 --- a/website/versioned_docs/version-0.72/hassio_addon_testing.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Local add-on testing -id: version-0.72-hassio_addon_testing -original_id: hassio_addon_testing ---- - -The fastest way to develop add-ons is by adding them to your local add-on repository. To access your local add-on repository, install either the [Samba add-on] or [SSH add-on]. - -Right now add-ons will work with images that are stored on Docker Hub (using `image` from add-on config). Without `image` inside local add-ons repository it to be built on the device. - -## Local build - -You can build and try the addon on your developer machine also. Move all addon stuff into a temp folder. If you use `FROM $BUILD_FROM` you need set a base image with build args. Normally you can use follow base images: - -- armhf: `homeassistant/armhf-base:latest` -- aarch64: `homeassistant/aarch64-base:latest` -- amd64: `homeassistant/amd64-base:latest` -- i386: `homeassistant/i386-base:latest` - -Use `docker` to build the test addon: `docker build --build-arg BUILD_FROM="homeassistant/amd64-base:latest" -t local/my-test-addon .` - -## Local run - -Create a new folder for data and add a test _options.json_ file. After that you can run your add-on with: `docker run --rm -v /tmp/my_test_data:/data -p PORT_STUFF_IF_NEEDED local/my-test-addon` - -## Logs - -All stdout and stderr are redirected to the Docker logs. The logs can be fetched from the add-on page inside the Hass.io panel in Home Assistant. - -[Samba add-on]: https://www.home-assistant.io/addons/samba/ -[SSH add-on]: https://www.home-assistant.io/addons/ssh/ diff --git a/website/versioned_docs/version-0.72/hassio_addon_tutorial.md b/website/versioned_docs/version-0.72/hassio_addon_tutorial.md deleted file mode 100644 index d17967ca..00000000 --- a/website/versioned_docs/version-0.72/hassio_addon_tutorial.md +++ /dev/null @@ -1,179 +0,0 @@ ---- -title: Tutorial: Making your first add-on -id: version-0.72-hassio_addon_tutorial -original_id: hassio_addon_tutorial ---- - -So you've got Home Assistant going and you've been enjoying the built-in add-ons but you're missing this one application. Time to make your own add-on! In Hass.io 0.24 we introduced the option to have local add-ons be build on your device. This is great for developing new add-ons locally. - -To get started with developing add-ons, we first need access to where Hass.io looks for local add-ons. For this you can use the Samba add-on or the SSH add-on. - -For Samba, once you have enabled and started it, your Hass.io instance will show up in your local network tab and share a folder called "addons". This is the folder to store your custom add-ons. - -If you are on macOS and the folder is not showing up automatically, go to Finder and press CMD+K then enter 'smb://hassio.local' - -![Screenshot of Windows Explorer showing a folder on the Hass.io server](/img/en/hass.io/tutorial/samba.png) - -For SSH, you will have to install it. Before you can start it, you will have to have a private/public key pair and store your public key in the add-on config ([see docs for more info][ssh]). Once started, you can SSH to Hass.io and store your custom add-ons in "/addons". - -![Screenshot of Putty connected to Hass.io](/img/en/hass.io/tutorial/ssh.png) - -Once you have located your add-on directory, it's time to get started! - -[ssh]: https://www.home-assistant.io/addons/ssh/ - -## Step 1: The basics - - - Create a new directory called `hello_world` - - Inside that directory create three files. - -`Dockerfile`: -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -`config.json`: -```json -{ - "name": "Hello world", - "version": "1", - "slug": "hello_world", - "description": "My first real add-on!", - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {} -} -``` - -`run.sh`: -```bash -echo Hello world! -``` - -## Step 2: Installing and testing your add-on - -Now comes the fun part, time to open the Hass.io UI and install and run your add-on. - - - Open the Home Assistant frontend - - Go to the Hass.io panel - - On the top right click the shopping basket to go to the add-on store. - -![Screenshot of the Hass.io main panel](/img/en/hass.io/screenshots/main_panel_addon_store.png) - - - On the top right click the refresh button - - You should now see a new card called "Local" that lists your add-on! - -![Screenshot of the local repository card](/img/en/hass.io/screenshots/local_repository.png) - - - Click on your add-on to go to the add-on details page. - - Install your add-on - - Start your add-on - - Refresh the logs of your add-on, you should now see "Hello world!" in your logs. - -![Screenshot of the add-on logs](/img/en/hass.io/tutorial/addon_hello_world_logs.png) - -### I don't see my add-on?! - -Oops! You clicked refresh in the store and your add-on didn't show up. Or maybe you just updated an option, clicked refresh and saw your add-on disappear. - -When this happens, it means that your `config.json` is invalid. It's either invalid JSON or one of the specified options is incorrect. To see what went wrong, go to the Hass.io panel and in the supervisor card click on "View logs". This should bring you to a page with the logs of the supervisor. Scroll to the bottom and you should be able to find the validation error. - -Once you fixed the error, go to the add-on store and click refresh again. - -## Step 3: Hosting a server - -Until now we've been able to do some basic stuff, but it's not very useful yet. So let's take it one step further and host a server that we expose on a port. For this we're going to use the built-in HTTP server that comes with Python 3. - -To do this, we will need to update our files as follows: - - - `Dockerfile`: Install Python 3 - - `config.json`: Make the port from the container available on the host - - `run.sh`: Run the Python 3 command to start the HTTP server - -Add to your `Dockerfile` before `RUN`: - -``` -# Install requirements for add-on -RUN apk add --no-cache python3 - -# Python 3 HTTP Server serves the current working dir -# So let's set it to our add-on persistent data directory. -WORKDIR /data -``` - -Add "ports" to `config.json`. This will make TCP on port 8000 inside the container available on the host on port 8000. - -```json -{ - "name": "Hello world", - "version": "0.2", - "slug": "hello_world", - "description": "My first real add-on!", - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {}, - "ports": { - "8000/tcp": 8000 - } -} -``` - -Update `run.sh` to start the Python 3 server: - -``` -python3 -m http.server -``` - -## Step 4: Installing the update - -Since we updated the version number in our `config.json`, Home Assistant will show an update button when looking at the add-on details. You might have to refresh your browser or click the refresh button in the add-on store for it to show up. If you did not update the version number, you can also uninstall and install the add-on again. After installing the add-on again, make sure you start it. - -Now navigate to [http://hassio.local:8000](http://hassio.local:8000) to see our server in action! - -![Screenshot of the file index served by the add-on](/img/en/hass.io/tutorial/python3-http-server.png) - -## Bonus: Working with add-on options - -In the screenshot you've probably seen that our server only served up 1 file: `options.json`. This file contains the user configuration for this add-on. Because we specified an empty "config" and "schema" in our `config.json`, the file is currently empty. - -Let's see if we can get some data into that file! - -To do this, we need to specify the default options and a schema for the user to change the options. - -Change the options and schema entries in your `config.json` with the following: - -```json -{ - … - - "options": { - "beer": true, - "wine": true, - "liquor": false, - "name": "world", - "year": 2017 - }, - "schema": { - "beer": "bool", - "wine": "bool", - "liquor": "bool", - "name": "str", - "year": "int" - }, - - … -} -``` - -Refresh the add-on store and re-install your add-on. You will now see the options available in the add-on config screen. When you now go back to our Python 3 server and download `options.json`, you'll see the options you set. [Example of how options.json can be used inside `run.sh`](https://github.com/home-assistant/hassio-addons/blob/master/mosquitto/run.sh#L4-L6) diff --git a/website/versioned_docs/version-0.72/hassio_debugging.md b/website/versioned_docs/version-0.72/hassio_debugging.md deleted file mode 100644 index f81debce..00000000 --- a/website/versioned_docs/version-0.72/hassio_debugging.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Debugging Hass.io -id: version-0.72-hassio_debugging -original_id: hassio_debugging ---- - -> This section is not for users. Use the [SSH add-on] to SSH into Hass.io. This is for developers of Hass.io. Do not ask for support if you are using these options. - -[SSH add-on]: https://www.home-assistant.io/addons/ssh/ - -The following debug tips and tricks are for people who are running the Hass.io image and are working on the base image. If you use the generic Linux installer script, you should be able to access your host and logs as per your host. - -## SSH access to the host - -Create an `authorized_keys` file containing your public key, and place it in the root of the boot partition of your SD card. Once the device is booted, you can access your device as root over SSH on port 22222. - -Windows instructions how to generate and use private/public keys with Putty are [here][windows-keys]. Instead of the droplet instructions, add the public key as per above instructions. - -Alternative instructions, for Mac, Windows and Linux can be found [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#platform-mac). - -Follow steps 1-4 under 'Generating a new SSH key' (The other sections are not applicable to Hass.io and can be ignored.) - -Step 3 in the link above, shows the path to the private key file `id_rsa` for your chosen operating system. Your public key, `id_rsa.pub`, is saved in the same folder. Next, select all text from text box "Public key for pasting into OpenSSH authorized_keys file" and save it to the root of your SD card as `authorized_keys`. - -> Make sure when you are copying the public key to the root of the /resin-boot partition of the SD card that you rename the file correctly to `authorized_keys` with no `.pub` file extension. - -You should then be able to SSH into your Hass.io device. On mac/linux, use: -``` -ssh root@hassio.local -p 22222 -``` - -## Checking the logs - -```bash -# Logs from the supervisor service on the Host OS -journalctl -f -u resin-supervisor.service - -# Hass.io supervisor logs -docker logs resin_supervisor - -# Home Assistant logs -docker logs homeassistant -``` - -[windows-keys]: https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-putty-on-digitalocean-droplets-windows-users diff --git a/website/versioned_docs/version-0.72/hassio_hass.md b/website/versioned_docs/version-0.72/hassio_hass.md deleted file mode 100644 index 8d4c72cc..00000000 --- a/website/versioned_docs/version-0.72/hassio_hass.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Hass.io <> Home Assistant integration development -sidebar_label: HASS Integration development -id: version-0.72-hassio_hass -original_id: hassio_hass ---- - -These steps will help you connect your local Home Assistant to a remote Hass.io instance. You can then make changes locally to either the Hass.io component or the frontend and test it out against a real instance. - -For this guide, we're going to assume that you have an Hass.io instance up and running. If you don't, you can use the generic installation method to install it inside a [virtual machine](https://github.com/home-assistant/hassio-build/tree/master/install#install-hassio). - -## SSH Access - -To develop for the frontend, we're going to need SSH access to the host machine. - -- If you're using a standard Hass.io installation, check [these instructions](hassio_debugging.md#ssh-access-to-the-host). -- If you're using the generic installer on a VM, setup port forwarding from the virtual machine port 22 to port 10022 on the host. You can then connect to it using `ssh your-username@127.0.0.1 -p 10022`. -- If you're using the generic installer on your own machine, check the manual for your operating system. - -## Getting connection details - -To connect to a remote Hass.io from Home Assistant, we need two pieces of information: the location where the supervisor API is running and an auth token to connect to it. - -To get these info, do the following steps: - - - SSH into the Hass.io host machine (this is not the SSH add-on!) - - If you're using a generic installation, run `sudo bash` to change to root. - - Run `docker inspect homeassistant | grep HASSIO`. The output should contain a value for `HASSIO` and `HASSIO_TOKEN`. `HASSIO` should be an ip address and `HASSIO_TOKEN` is a string with random letters/numbers. - - Disconnect the SSH session. - - ## Having Home Assistant connect to remote Hass.io - - The connection with the supervisor is hidden inside the host and is only accessible from applications running on the host. So to make it accessible for our Home Assistant instance, we will need to route the connection to our computer running Home Assistant. We're going to do this by forwarding ports via an SSH connection. - -We are going to SSH from our machine running Home Assistant into the remote Hass.io host. We're going to configure our SSH connection to forward all local connections to localhost port 10081 to be sent from the Hass.io host to the IP address that we got as `HASSIO` value in the last step. - -> These instructions are for non-Windows systems - -We can setup port forwarding from the Hass.io machine to our machine by adding the following line to the SSH command: `-L10081::80`. For example, if the value of HASSIO was `172.30.32.2` and you run Hass.io generic installer via a VM, the command would look like this: - -```bash -ssh paulus@127.0.0.1 -p 10022 -L10081:172.30.32.2:80 -``` - -As long as the terminal window with the SSH connection is open, the port forwarding will remain active. - -Now let's open a new terminal window and start Home Assistant. - -First, make sure Home Assistant will load the Hass.io component by adding `hassio:` to your `configuration.yaml` file. Next, we will need to tell Hass.io component how to connect to the remote Hass.io instance, we do this by setting the `HASSIO` and `HASSIO_TOKEN` environment variables when starting Home Assistant. Note that the `HASSIO` value is not the same as the one that we saw above. - -```bash -HASSIO=127.0.0.1:10081 HASSIO_TOKEN= hass -``` - -Voila. Your local Home Assistant installation will now connect to a remote Hass.io instance. - -## Frontend development - -> This requires Home Assistant 0.71 or later. - -We need a couple more steps to do frontend development. First, make sure you have a Home Assistant frontend development set up ([instructions](frontend_index.md)). - -Update the Hass.io component configuration in your `configuration.yaml` to point at the frontend repository: - -```yaml -# configuration.yaml -hassio: - development_repo: /home/paulus/dev/hass/home-assistant-polymer -``` - -To build a local version of the Hass.io panel, go to the frontend repository and run: - -```bash -cd hassio -script/build_hassio -``` - -Now start Home Assistant as discussed in the previous section and it will now connect to the remote Hass.io but show your local frontend. - -We're currently transitioning in how we're building the frontend so we don't have an incremental development mode just yet. For now, after making a local change, run `script/build_hassio` again. diff --git a/website/versioned_docs/version-0.72/intent_builtin.md b/website/versioned_docs/version-0.72/intent_builtin.md deleted file mode 100644 index ee946d6d..00000000 --- a/website/versioned_docs/version-0.72/intent_builtin.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: Built-in intents -id: version-0.72-intent_builtin -original_id: intent_builtin ---- - -Home Assistant comes with a couple of built-in intents. These intents aim to offer similar functionality as exposed via the services. All built-in intents are prefixed with "Hass" to avoid collision with user defined intents. - -## Core - -### HassTurnOff - -Turn an entity off. - -| Slot name | Type | Required | Description -| --------- | ---- | -------- | ----------- -| name | string | Yes | Name of the entity to turn off. - -### HassTurnOn - -Turn an entity on. - -| Slot name | Type | Required | Description -| --------- | ---- | -------- | ----------- -| name | string | Yes | Name of the entity to turn on. - -### HassToggle - -Toggle the state of an entity. - -| Slot name | Type | Required | Description -| --------- | ---- | -------- | ----------- -| name | string | Yes | Name of the entity to toggle. - -## Cover - -### HassOpenCover - -Open a cover. - -| Slot name | Type | Required | Description -| --------- | ---- | -------- | ----------- -| name | string | Yes | Name of the cover entity to open. - -### HassCloseCover - -Close a cover. - -| Slot name | Type | Required | Description -| --------- | ---- | -------- | ----------- -| name | string | Yes | Name of the cover entity to close. - -## Light - -### HassLightSet - -Set the state of a light. - -| Slot name | Type | Required | Description -| --------- | ---- | -------- | ----------- -| name | string | Yes | Name of the entity to toggle. -| color | string, name of valid color | No | Color to change the light to. -| brightness | integer, 0-100 | No | Brightness to change the light to. - -## Shopping List - -### HassShoppingListAddItem - -Add an item to the shopping list. - -| Slot name | Type | Required | Description -| --------- | ---- | -------- | ----------- -| item | string | Yes | Name of item to add to the list. - -### HassShoppingListLastItems - -List the last 5 items on the shopping list. - -_This intent has no slots._ diff --git a/website/versioned_docs/version-0.72/intent_conversation.md b/website/versioned_docs/version-0.72/intent_conversation.md deleted file mode 100644 index 0c892561..00000000 --- a/website/versioned_docs/version-0.72/intent_conversation.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Registering sentences -id: version-0.72-intent_conversation -original_id: intent_conversation ---- - -The conversation component handles incoming commands from the frontend and converts them to intents. It does this based on registered sentences. - -As a component, you can register sentences with the conversation component to allow it to be remote controlled. Refer to named slots by putting the slot name between curly braces: `{item}`. Use square brackets around (partial) words to mark them as optional. - -Example code: - -```python -async def async_setup(hass, config): - hass.components.conversation.async_register('MyCoolIntent', [ - 'I think that {object} is [very] cool', - 'Nothing is cooler than {object}' - ]) -``` - -If a sentence like "I think that beer is cool" comes in, the conversation component will generate an intent of type `MyCoolIntent` and with 1 slot, named `object` and value `beer`. diff --git a/website/versioned_docs/version-0.72/intent_firing.md b/website/versioned_docs/version-0.72/intent_firing.md deleted file mode 100644 index 773eefa0..00000000 --- a/website/versioned_docs/version-0.72/intent_firing.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Firing intents -id: version-0.72-intent_firing -original_id: intent_firing ---- - -When you fire an intent, you will get a response back or an error will be raised. It is up to the component to return the result to the user. - -Example code to handle an intent in Home Assistant. - -```python -from homeassistant.helpers import intent - -intent_type = 'TurnLightOn' -slots = { - 'entity': { 'value': 'Kitchen' } -} - -try: - intent_response = yield from intent.async_handle( - hass, 'example_component', intent_type, slots - ) - -except intent.UnknownIntent as err: - _LOGGER.warning('Received unknown intent %s', intent_type) - -except intent.InvalidSlotInfo as err: - _LOGGER.error('Received invalid slot data: %s', err) - -except intent.IntentError: - _LOGGER.exception('Error handling request for %s', intent_type) -``` - -The intent response is an instance of `homeassistant.helpers.intent.IntentResponse`. - -| Name | Type | Description | -| ---- | ---- | ----------- | -| `intent` | Intent | Instance of intent that triggered response. | -| `speech` | Dictionary | Speech responses. Each key is a type. Allowed types are `plain` and `ssml`. | -| `card` | Dictionary | Card responses. Each key is a type. | - -Speech dictionary values: - -| Name | Type | Description | -| ---- | ---- | ----------- | -| `speech` | String | The text to say -| `extra_data` | Any | Extra information related to this speech. - -Card dictionary values: - -| Name | Type | Description | -| ---- | ---- | ----------- | -| `title` | String | The title of the card -| `content` | Any | The content of the card diff --git a/website/versioned_docs/version-0.72/intent_handling.md b/website/versioned_docs/version-0.72/intent_handling.md deleted file mode 100644 index 738bd404..00000000 --- a/website/versioned_docs/version-0.72/intent_handling.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Handling intents -id: version-0.72-intent_handling -original_id: intent_handling ---- - -Any component can register to handle intents. This allows a single component to handle intents fired from multiple voice assistants. - -A component has to register an intent handler for each type that it wants to handle. Intent handlers have to extend `homeassistant.helpers.intent.IntentHandler` - -```python -import asyncio -from homeassistant.helpers import intent - -DATA_KEY = 'example_key' - -@asyncio.coroutine -def async_setup(hass, config): - hass.data[DATA_KEY] = 0 - intent.async_register(hass, CountInvocationIntent()) - - -class CountInvocationIntent(intent.IntentHandler): - """Handle CountInvocationIntent intents.""" - - # Type of intent to handle - intent_type = 'CountInvocationIntent' - - # Optional. A validation schema for slots - # slot_schema = { - # 'item': cv.string - # } - - @asyncio.coroutine - def async_handle(self, intent_obj): - """Handle the intent.""" - intent_obj.hass.data[DATA_KEY] += 1 - - response = intent_obj.create_response() - response.async_set_speech( - "This intent has been invoked {} times".format( - intent_obj.hass.data[DATA_KEY])) - return response -``` diff --git a/website/versioned_docs/version-0.72/intent_index.md b/website/versioned_docs/version-0.72/intent_index.md deleted file mode 100644 index dc71c11a..00000000 --- a/website/versioned_docs/version-0.72/intent_index.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: Intents -sidebar_label: Introduction -id: version-0.72-intent_index -original_id: intent_index ---- - -An intent is a description of a user's intention. Intents are generated by user actions, like asking Amazon Echo to turn on a light. - - - Architectural overview of intents in Home Assistant - - - -Intents are fired by components that receive them from external sources/services. Conversation, Alexa, API.ai and Snips are currently sourcing intents. - -Any component can handle intents. This makes it very easy for developers to integrate with all voice assistants at once. - -Intents are implemented using the `homeassistant.helpers.intent.Intent` class. It contains the following properties: - -| Name | Type | Description | -| ---- | ---- | ----------- | -| `hass` | Home Assistant | The Home Assistant instance that fired the intent. -| `platform` | string | The platform that fired the intent -| `intent_type` | string | The type (name) of the intent -| `slots` | dictionary | Contains the slot values keyed by slot name. -| `text_input` | string | Optional. The raw text input that initiated the intent. - -Description of the slots dictionary values. - -| Name | Type | Description | -| ---- | ---- | ----------- | -| Value | anything | Value of the slot. diff --git a/website/versioned_docs/version-0.72/internationalization_backend_localization.md b/website/versioned_docs/version-0.72/internationalization_backend_localization.md deleted file mode 100644 index 4b9092b1..00000000 --- a/website/versioned_docs/version-0.72/internationalization_backend_localization.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Backend Localization -id: version-0.72-internationalization_backend_localization -original_id: internationalization_backend_localization ---- - -## Translation Strings -Platform translation strings are stored as JSON in the [home-assistant](https://github.com/home-assistant/home-assistant) repository. These files must be located adjacent to the component/platform they belong to. Components must have their own directory, and the file is simply named `strings.json` in that directory. For platforms, they are named `strings..json` in the platform directory. This file will contain the different strings that will be translatable. - -In order to test changes to translation files, the translation strings must be compiled into Home Assistant’s translation directories by running the following script: - -```bash -$ script/translations_develop -``` - -After the pull request with the strings file is merged into the `dev` branch, the strings will be automatically uploaded to Lokalise, where contributors can submit translations. The translated strings in Lokalise will be periodically pulled in to the home-assistant repository. - -## States Localization -The first step when localizing platform states is to ensure that the states defined in the actual platform code are defined in `snake_case`. The states should not contain capital letters or spaces. Next, the strings file needs to be created. The states should exist under the `state` key, and map the backend state keys to their English translations. [The season sensor localization](https://github.com/home-assistant/home-assistant/pull/12453/commits/bb2f328ce10c3867990e34a88da64e2f8dc7a5c4) is a good example. - -## Configuration Flow Localization -The translation strings for the configuration flow handler are defined under the `config` key. An example strings file below describes the different supported keys: - -```json -{ - "config": { - "title": "This title is shown in the integrations list", - "step": { - "init": { - "title": "The user visible title of the `init` step.", - "description": "Markdown that is shown with the step.", - "data": { - "api_key": "The label for the `api_key` input field" - } - } - }, - "error": { - "invalid_api_key": "This message will be displayed if `invalid_api_key` is returned as a flow error." - }, - "abort": { - "stale_api_key": "This message will be displayed if `stale_api_key` is returned as the abort reason." - } - } -} -``` diff --git a/website/versioned_docs/version-0.72/internationalization_custom_component_localization.md b/website/versioned_docs/version-0.72/internationalization_custom_component_localization.md deleted file mode 100644 index 3166b768..00000000 --- a/website/versioned_docs/version-0.72/internationalization_custom_component_localization.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Custom Component Localization -id: version-0.72-internationalization_custom_component_localization -original_id: internationalization_custom_component_localization ---- - -## Translation Strings -Unlike localized strings merged in the home-assistant repository, custom components cannot take advantage of Lokalise for user submitted translations. However, custom component authors can still include translation with their components. These will be read from the `.translations` directory, adjacent to the component source file. They are named `..json`, unless the custom component exists in its own directory, in which case the file is simply named `.json` in the `.translations` directory. - -These files follow the same formatting as [backend translation string files](internationalization_backend_localization.md), but a copy will exist for each translated language. - -The language codes follow the [BCP47](https://tools.ietf.org/html/bcp47) format. The [frontend translation files](https://github.com/home-assistant/home-assistant-polymer/tree/master/translations) can also be referred to if you are unsure of the correct language code to use. - -The frontend will serve these files after Home Assistant is restarted. diff --git a/website/versioned_docs/version-0.72/internationalization_index.md b/website/versioned_docs/version-0.72/internationalization_index.md deleted file mode 100644 index 2cb59420..00000000 --- a/website/versioned_docs/version-0.72/internationalization_index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Internationalization -id: version-0.72-internationalization_index -original_id: internationalization_index ---- - -The Home Assistant internationalization project includes preparing platforms and the frontend for localization, as well as the actual translation of localized strings. - -Some compmonents and platforms will have strings that need to be localized specifically for that platform. These strings are managed in the core [home-assistant](https://github.com/home-assistant/home-assistant) repository. The Home Assistant backend will serve strings to the clients based on the loaded components in the running instance. - -There are also localizable strings that exist only on the frontend. These strings are managed in the [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer) repository. These strings are stored with the frontend and don’t depend on the backend configuration. - -Our strings are translated by the community using the online translation tool [Lokalise](https://lokalise.co/). diff --git a/website/versioned_docs/version-0.72/internationalization_translation.md b/website/versioned_docs/version-0.72/internationalization_translation.md deleted file mode 100644 index 201055a2..00000000 --- a/website/versioned_docs/version-0.72/internationalization_translation.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Translation -id: version-0.72-internationalization_translation -original_id: internationalization_translation ---- - -## How to start -Translations for Home Assistant are managed through Lokalise, an online translation management tool. Our translations are split between two projects, a backend project for platform-specific translations, and a frontend project for UI translations. Click the links below to join both projects! Even if your language is completely translated, extra proofreading is a big help! Please feel free to review the existing translations, and vote for alternatives that might be more appropriate. - -- [Join the frontend translation team](https://lokalise.co/signup/3420425759f6d6d241f598.13594006/all/) -- [Join the backend translation team](https://lokalise.co/signup/130246255a974bd3b5e8a1.51616605/all/) - -For more information about the translation workflow, please see the [Lokalise translation workflow documents](https://docs.lokalise.co/category/iOzEuQPS53-for-team-leads-and-translators). - -> The translation of the Home Assistant frontend is still a work in progress. More phrases will be available for translation soon. - -## Translation placeholders - -Some translation strings will contain special placeholders that will be replaced later. Placeholders shown in square brackets `[]` are [Lokalise key references](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing). These are primarily used to link translation strings that will be duplicated. Different languages may not have the same duplicates as English, and are welcome to link duplicate translations that are not linked in English. Placeholders shown in curly brackets `{}` are [translation arguments](https://formatjs.io/guides/message-syntax/) that will be replaced with a live value when Home Assistant is running. Any translation argument placeholders present in the original string must be included in the translated string. These may include special syntax for defining plurals or other replacement rules. The linked format.js guide explains the syntax for adding plural definitions and other rules. - -## Rules -1. Only native speakers should submit translations. -2. Stick to [Material Design guidelines](https://material.io/guidelines/style/writing.html). -3. Don't translate or change proper nouns like `Home Assistant`, `Hass.io` or `Hue`. -4. For a region specific translation, keys that will be the same as the base translation should be filled with `[VOID]`. These will be replaced during our translation build process. -5. Translations under the `state_badge` keys will be used for the notification badge display. These translations should be short enough to fit in the badge label without overflowing. This can be tested in the Home Assistant UI either by editing the label text with your browsers development tools, or by using the States states dev tool icon developer tool in the Home Assistant UI. In the UI, enter a new entity ID (`device_tracker.test`), and enter the text you want to test in state. -6. If text will be duplicated across different translation keys, make use of the Lokalise key reference feature where possible. The base translation provides examples of this underneath the `states` translations. Please see the [Lokalise key referencing](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing) documentation for more details. - -## Adding a new language -If your language is not listed you can request it at [GitHub](https://github.com/home-assistant/home-assistant-polymer/issues/new). Please provide both the English name and the native name for your language. For example: -``` -English Name: German -Native Name: Deutsch -``` - -> Region specific translations (`en-US`, `fr-CA`) will only be included if translations for that region need to differ from the base language translation. - -### Maintainer steps to add a new language -1. Language tags have to follow [BCP 47](https://tools.ietf.org/html/bcp47). A list of most language tags can be found here: [IANA sutbtag registry](http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry). Examples: `fr`, `fr-CA`, `zh-Hans`. Only include the country code if country specific overrides are being included, and the base language is already translated. -2. Add the language tag and native name in `src/translations/translationMetadata.json`. Examples: "Français", "Français (CA)" -3. Add the new language in Lokalize. -Note: Sometimes you have to change the tag in Lokalise (Language -> Language settings -> custom ISO code). diff --git a/website/versioned_docs/version-0.72/lovelace_card_types.md b/website/versioned_docs/version-0.72/lovelace_card_types.md deleted file mode 100644 index 73f0f1e1..00000000 --- a/website/versioned_docs/version-0.72/lovelace_card_types.md +++ /dev/null @@ -1,110 +0,0 @@ ---- -title: Type Of Cards -sidebar_label: Cards -id: version-0.72-lovelace_card_types -original_id: lovelace_card_types ---- - -These cards are WIP and things may change. - -## Camera preview - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| type | string | **Required** | `camera-preview` -| entity | string | **Required** | Entity id of `camera` domain - -## Entities - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| type | string | **Required** | `entities` -| entities | list | **Required** | Entity id's -| title | string | Optional | Card title - -## Entity filter - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| type | string | **Required** | `entity-filter` -| filter | list | **Required** | See filter description -| card_config | object | `None` | Extra options to pass down to the card rendering the result. -| card | string | `entities` | Card to use to render the result. Follows same rules as card type. - -Filter options: - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| domain | string | Optional | Filter all entities that match the domain -| state | string | Optional | Match entities that match state. Note, in YAML, make sure you wrap it in quotes to make sure it is parsed as a string. -| entity_id | string | Optional | Filter entities by id, supports wildcards (`*living_room*`) - -## Entity picture - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| type | string | **Required** | `entity-picture` -| image | string | **Required** | URL of an image. -| entity | string | **Required** | Entity id to control via picture. - -## Glance - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| type | string | **Required** | `glance` -| entities | list | **Required** | Entity id's -| title | string | Optional | Card title - -## History graph - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| type | string | **Required** | `history-graph` -| entity | string | **Required** | Entity id of `history_graph` domain - -## Iframe - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| type | string | **Required** | `iframe` -| url | string | **Required** | iframe source url -| aspect_ratio | string | `"50%"` | Iframe height-width-ratio -| title | string | Optional | Card title - -## Markdown - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| type | string | **Required** | `markdown` -| content | string | **Required** | Content to render as [markdown](http://commonmark.org/help/). -| title | string | Optional | Card title - -## Media controller - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| type | string | **Required** | `media-control` -| entity | string | **Required** | Entity id of `media_player` domain - -## Picture glance - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| type | string | **Required** | `picture-glance` -| image | string | **Required** | URL of an image. -| entities | list | **Required** | Entity id's -| title | string | Optional | Card title - -## Plant info - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| type | string | **Required** | `plant-status` -| entity | string | **Required** | Entity id of `plant` domain - -## Weather forecast - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| type | string | **Required** | `weather-forecast` -| entity | string | **Required** | Entity id of `weather` domain diff --git a/website/versioned_docs/version-0.72/lovelace_custom_card.md b/website/versioned_docs/version-0.72/lovelace_custom_card.md deleted file mode 100644 index b59b3dbd..00000000 --- a/website/versioned_docs/version-0.72/lovelace_custom_card.md +++ /dev/null @@ -1,168 +0,0 @@ ---- -title: Custom Cards -id: version-0.72-lovelace_custom_card -original_id: lovelace_custom_card ---- - -You're not just limited to the cards that we decided to include in the Lovelace UI. You can build and use your own! - -## API - -- You define your custom card as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). It's up to you to decide how to render your DOM inside your element. You can use Polymer, Angular, Preact or any other popular framework (except for React – more info [here](https://custom-elements-everywhere.com/)). -- Home Assistant will set the `config` property when the configuration changes (rare). -- Home Assistant will set the `hass` property when the state of Home Assistant changes (frequent). Whenever the state changes, the component will have to update itself to represent the latest state. -- Home Assistant will call `getCardSize()` to request the size of the card. Size of the card is used for the automatic distribution of cards across columns. Both `config` and `hass` properties will be available. Defaults to `1` if function is not defined. - -## Defining your card - -Create a new file in your Home Assistant config dir as `/www/content-card-example.js` and put in the following contents: - -```js -class ContentCardExample extends HTMLElement { - set hass(hass) { - if (!this.content) { - const card = document.createElement('ha-card'); - card.header = 'Example card'; - this.content = document.createElement('div'); - this.content.style.padding = '0 16px 16px'; - card.appendChild(this.content); - this.appendChild(card); - } - - const entityId = this.config.entity; - const state = hass.states[entityId]; - const stateStr = state ? state.state : 'unavailable'; - - this.content.innerHTML = ` - The state of ${entityId} is ${stateStr}! -

- - `; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return 3; - } -} - -customElements.define('content-card-example', ContentCardExample); -``` - -## Referencing your new card - -In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `/www` directory, it will be accessible in your browser via the url `/local/`. - -```yaml -# Example ui-lovelace.yaml -resources: - - url: /local/content-card-example.js - type: js -views: -- name: Example - cards: - - type: "custom:custom-card-example" - entity: input_boolean.switch_tv -``` - -## Advanced example - -Resources to load in Lovelace can be imported as a JS script, an HTML import or as a JS module import. Below is an example of a custom card using JS modules that does all the fancy things. - -Create a new file in your Home Assistant config dir as `/www/wired-cards.js` and put in the following contents: - -```js -import 'https://unpkg.com/wired-card@0.6.5/wired-card.js?module'; -import 'https://unpkg.com/wired-toggle@0.6.5/wired-toggle.js?module'; -import { - LitElement, html -} from 'https://unpkg.com/@polymer/lit-element@^0.5.2/lit-element.js?module'; - -function loadCSS(url) { - const link = document.createElement('link'); - link.type = 'text/css'; - link.rel = 'stylesheet'; - link.href = url; - document.head.appendChild(link); -} - -loadCSS('https://fonts.googleapis.com/css?family=Gloria+Hallelujah'); - -class WiredToggleCard extends LitElement { - static get properties() { - return { - hass: Object, - config: Object, - } - } - - _render({ hass, config }) { - return html` - - - ${config.entities.map(ent => hass.states[ent]).map((state) => - html` -
- ${state.attributes.friendly_name} - -
- ` - )} -
- `; - } - - _toggle(state) { - this.hass.callService('homeassistant', 'toggle', { - entity_id: state.entity_id - }); - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return this.config.entities.length + 1; - } -} -customElements.define('wired-toggle-card', WiredToggleCard); -``` - -And for your configuration: - -```yaml -# Example ui-lovelace.yaml -resources: - - url: /local/wired-cards.js - type: module -views: -- name: Example - cards: - - type: "custom:wired-toggle-card" - entities: - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_livingroom - - input_boolean.switch_tv -``` diff --git a/website/versioned_docs/version-0.72/lovelace_index.md b/website/versioned_docs/version-0.72/lovelace_index.md deleted file mode 100644 index a4b8d614..00000000 --- a/website/versioned_docs/version-0.72/lovelace_index.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -title: Lovelace UI -sidebar_label: Introduction -id: version-0.72-lovelace_index -original_id: lovelace_index ---- - -> This is an experimental feature. Configuration might change in future versions. - -Starting with Home Assistant 0.72, we're experimenting with a new way of defining your interface. We're calling it the Lovelace UI. - -The Lovelace UI is: - - - **Extremely fast**. We create the user interface when the UI configuration changes. When a state changes, we just make the UI represent the current state. - - **Extremely customizable**. We have a new file for just configuration. In the past, we declined UI specific options because they did not fit in the state machine. They will fit in a configuration file for a user interface. - - **Extremely extensible**. It's based on the web standard [custom elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). Don't like the built-in cards? Make your own! Custom cards are treated the same as built-in cards and are configured the same way. [Check the docs.](lovelace_custom_card.md) - - **Making the backend faster**. With Lovelace, the backend will no longer need to maintain entities like groups for the sole purpose of showing them on the frontend. - -## How it works - -The old user interface relied solely on the state machine. This caused trouble as it meant that the state machine was now not only the source for device states, but also for user interface configuration. With Lovelace, we're taking a completely different approach. All user interface configuration will live in a separate file, controlled by the user. - -![Visual comparison of old configuration versus new configuration](/img/en/frontend/lovelace-ui-comparison.png) - - - -## Trying it out - -Create a new file `/ui-lovelace.yaml` and add the following content: - -```yaml -name: My Awesome Home -views: - # The name of a view will be used as tab title. - # Might be used for other things in the future. - - name: Example - # Each view can have a different theme applied. Theme should be defined in the frontend. - theme: dark-mode - # The cards to show on this view. - cards: - # The entities card will take a list of entities and show their state. - - type: entities - # Title of the entities card - title: Example - # The entities here will be shown in the same order as specified. - entities: - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_livingroom - - input_boolean.switch_tv - - # The filter card will filter available entities for certain criteria - # and render it as type 'entities'. - - type: entity-filter - # Filter criteria. They are all optional. - filter: - - domain: input_boolean - state: 'on' - # This config will be passed to the card rendering the filter results - card_config: - title: Input booleans that are on - - # Specify a tab_icon if you want the view tab to be an icon. - - tab_icon: mdi:home-assistant - # Name of the view. Will be used as the tooltip for tab icon - name: Second view - cards: - - type: entities - title: Lots of Kitchen AC - entities: - # It is totally possible to render duplicates. - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_kitchen -``` - -Add to your `configuration.yaml`: - -```yaml -input_boolean: - switch_ac_kitchen: - name: AC kitchen - switch_ac_livingroom: - name: AC living room - switch_tv: - name: TV -``` - -Now restart Home Assistant, navigate to `/lovelace`. When you make changes to `ui-lovelace.yaml`, you don't have to restart Home Assistant or refresh the page. Just hit the refresh button at the top of the UI. - -## Current limitations - -This is the very very early version aimed at gathering feedback. Discussion and suggestions are welcome in the [ui-schema repository](https://github.com/home-assistant/ui-schema). - -## Change log - -**Home Assistant 0.72** - -- Initial release of the Lovelace UI. diff --git a/website/versioned_docs/version-0.72/maintenance.md b/website/versioned_docs/version-0.72/maintenance.md deleted file mode 100644 index 53651e32..00000000 --- a/website/versioned_docs/version-0.72/maintenance.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Maintenance -id: version-0.72-maintenance -original_id: maintenance ---- - -This page documents a couple of points for maintaining the Home Assistant code. Most of the tasks don't need to be performed on a regular base thus the steps, used tools, or details are preserved here. - -## Source code - -### Line separator - -People are using various operating systems to develop components and platforms for Home Assistant. This could lead to different line endings on file. We prefer `LN`. Especially Microsoft Windows tools tend to use `CRLF`. - -```bash -$ find homeassistant -name "*.py" -exec file {} \; | grep BOM -$ find homeassistant -name "*.py" -exec file {} \; | grep CRLF -``` - -To fix the line separator, use `dos2unix` or `sed`. - -```bash -$ dos2unix homeassistant/components/notify/kodi.py -``` - -### File permissions - -Most files don't need to the be executable. `0644` is fine. - -### Dependencies - -A lot of components and platforms depends on third-party Python modules. The dependencies which are stored in the `requirements_*.txt` files are tracked by [gemnasium](https://gemnasium.com/github.com/home-assistant/home-assistant) and [Requires.io](https://requires.io/github/home-assistant/home-assistant/requirements/?branch=dev). - -If you update the requirements of a component/platform through the `REQUIREMENTS = ['modules-xyz==0.3']` entry, run the provided script to update the `requirements_*.txt` file(s). - -```bash -$ script/gen_requirements_all.py -``` - -Start a test run of Home Assistant. If that was successful, include all files in a Pull Request. Add a short summary of the changes, a sample configuration entry, details about the tests you performed to ensure the update works, and other useful information to the description. - - -## Documentation - -- Merge `current` into `next` on a regular base. -- Optimize the images. - diff --git a/website/versioned_docs/version-0.72/misc.md b/website/versioned_docs/version-0.72/misc.md deleted file mode 100644 index 470704fc..00000000 --- a/website/versioned_docs/version-0.72/misc.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Miscellaneous -id: version-0.72-misc -original_id: misc ---- - -Catch all category. Topics are not related to one another. diff --git a/website/versioned_docs/version-0.72/releasing.md b/website/versioned_docs/version-0.72/releasing.md deleted file mode 100644 index e3beb84b..00000000 --- a/website/versioned_docs/version-0.72/releasing.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Releasing -id: version-0.72-releasing -original_id: releasing ---- - -This page describes the steps for publishing a new Home Assistant release. Those steps requires that you don't use forks but work with the repositories themself. The [hass-release](https://github.com/home-assistant/hass-release) script is a helper to do a release. - -### Release preparation (3 days before release) - -### GitHub - -1. Merge `master` into `dev` to make the PR mergeable. -1. Cut a release branch from `dev`. Example name `release-0-57`. -1. Create a pull request from the release branch to `master` with the upcoming release number as the title. -1. Update `homeassistant/const.py` with the correct version number (remove the `dev` tag) and push that commit to release branch. - -### Website - -1. Merge `current` into `next` -1. Cut release branch of `next`. For example `release-0-57`. -1. Open a PR from release branch to `current` with the upcoming release number as the title. - -## Release day - -From creating the release branch till it has been merged, we tag bugfixes with the milestone for the release (create if doesn't exist). - -### GitHub - -1. Cherry-pick the milestoned PRs that need to get into the release `python3 -m hassrelease milestone_cherry_pick 0.57` -1. Run `python3 -m hassrelease release_notes 0.56` for the release notes. -1. Once the release notes has been generated, issue `python3 -m hassrelease milestone_close 0.56` -1. Merge pull request (DO NOT SQUASH!). Use `Merge pull request`. -1. Go to [releases](https://github.com/home-assistant/home-assistant/releases), click `Draft a new release` and tag a new release on the `master` branch. "Tag version" and "Release title" are the version number (`O.x` for major version, `0.x.y` for minor and bug fix releases). Release description is the text from PR. Press "Publish release" to finish the process. -1. Merge `master` into `dev`. -1. Update `homeassistant/const.py` with the upcoming version number (including the `dev` tag) and push that commit to the `dev` branch. - -### Website - -1. Create a blog post in the release branch and base it on the text of the PR in the main repository. Add images, additional text, links, etc. if it adds value. Tag each platform/component in a message to documentation. -1. Create missing documentation as stubs. -1. Run `credits_generator`. -1. Update `_config.yml` with a link to the new release blog post and version number (at the bottom of the file). -1. Merge `current` into release branch (`$ git checkout release-0-40 && git merge current`) to make the PR mergeable. -1. Merge pull request (blog post, updated frontpage, and all new documentation) to `current`. DO NOT SQUASH! -1. Merge `current` into `next`. - -### Docker Hub - -Tags on Docker hub are automatically created when a release has been created on GitHub. - -### Python Package Index - -Checkout the `master` branch and run `script/release` to publish the new release on [Python Package Index](https://pypi.python.org). - -### Social media - -1. Use [hootsuite](https://hootsuite.com/dashboard) to publish a link to the release post on social media. - -## Bugfix Release - -1. Checkout `master` and update it. `git checkout master && git pull --rebase` -1. Create a new release branch from `master`. `git checkout -b release-0-56-2` -1. Cherry-pick the PRs which were milestoned. -1. Update `homeassistant/const.py` with the correct version number (increment `PATCH_VERSION`) and push that commit to release branch. -1. Create a pull request from the release branch to `master` with the upcoming release number as the title. -1. Merge pull request (DO NOT SQUASH!). Use `Merge pull request`. -1. Go to [releases](https://github.com/home-assistant/home-assistant/releases), click `Draft a new release` and tag a new release on the `master` branch. "Tag version" and "Release title" are the version number (`O.x` for major version, `0.x.y` for minor and bug fix releases). Release description is the text from PR. Press "Publish release" to finish the process. -1. Publish the new release on PyPI. diff --git a/website/versioned_docs/version-0.73.0/auth_api.md b/website/versioned_docs/version-0.73.0/auth_api.md deleted file mode 100644 index 7f0a139b..00000000 --- a/website/versioned_docs/version-0.73.0/auth_api.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: Authentication API -sidebar_label: API -id: version-0.73.0-auth_api -original_id: auth_api ---- - -> This is experimental. It is not persisted and is not yet intended for production. - -This page will describe the steps required to fetch an access token for a user and how to refresh it. We follow the OAuth 2 specification. - -## Requirements - -A client needs to be created inside Home Assistant before a client can request users to authorize it or fetch a new access token. The only way currently to create a client is programmatically: - -```python -client = await hass.auth.async_get_or_create_client( - 'Example client', - redirect_uris=['http://www.example.com/hass_callback'] -) -print(client.id) -``` - -## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) - - - The authorize url should contain `client_id`, `redirect_uri` and, if available, `client_secret` as query parameters. Example: `http://your-instance.com/auth/authorize?client_id=ABCDE&client_secret=QWERTY&redirect_uri=https%3A%2F%2Fexample.com%2Fhass_callback` - - The user will navigate to this link, log into Home Assistant and authorize the client. - - Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code as part of the query parameters. Example: https://example.com/hass_callback?code=12345 - - This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section). - - As specified in the OAuth 2 specification, it is possible to pass an optional state string to the authorize url using the `state` query parameter. This string will be added as query parameter to the redirect url. - -## Token - -The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. - -All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`. - -### Authorization code - -Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is: - -``` -grant_type=authorization_code&code=12345 -``` - -The return response will be an access and refresh token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "refresh_token": "IJKLMNOPQRST", - "token_type": "Bearer" -} -``` - -### Refresh token - -Use the grant type `refresh_token` to retrieve an access token using a refresh token. The request body is: - -``` -grant_type=refresh_token&refresh_token=QWERTY -``` - -The return response will be an access token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "token_type": "Bearer" -} -``` - -## Making authenticated requests - -Once you have an access token, you can make authenticated requests to the Home Assistant APIs. - -For the websocket connection, pass the access token in the [authentication message](http://localhost:3000/docs/en/external_api_websocket.html#authentication-phase). - -For HTTP requests, pass the token type and access token as the authorization header: - -``` -Authorization: Bearer ABCDEFGH -``` - -If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and the client should ask the user to authorize again. diff --git a/website/versioned_docs/version-0.73.0/development_guidelines.md b/website/versioned_docs/version-0.73.0/development_guidelines.md deleted file mode 100644 index 8453529f..00000000 --- a/website/versioned_docs/version-0.73.0/development_guidelines.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Style guidelines -id: version-0.73.0-development_guidelines -original_id: development_guidelines ---- - -Home Assistant enforces strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. We automatically test every pull request as part of the linting process with [Coveralls](https://coveralls.io/github/home-assistant/home-assistant) and [Travis CI](https://travis-ci.org/home-assistant/home-assistant). - -Summary of the most relevant points: - -- Line length is limited to 79 characters (see below). -- Use 4 spaces per indentation level. We don't use tabs. -- Comments should be full sentences and end with a period. -- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered. -- Constants and the content of lists and dictionaries should be in alphabetical order. -- Avoid trailing whitespace but surround binary operators with a single space. -- Line separator should be set to `LF`. - -The maximum line length comes directly from the [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/#maximum-line-length), and is also used by the Python standard library. All code must pass these linting checks, and no exceptions will be made. There have already been numerous requests to increase the maximum line length, but after evaluating the options, the Home Assistant maintainers have decided to stay at 79 characters. This decision is final. - -Those points may require that you adjust your IDE or editor settings. - -## Our recommendations - -For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code unified. - -### Quotes - -Use single quotes `'` for single word and `"` for multiple words or sentences. - -```python -ATTR_WATERLEVEL = 'level' -CONF_ATTRIBUTION = "Data provided by the WUnderground weather service" -SENSOR_TYPES = { - 'alerts': ['Alerts', None], -} -``` - -### File headers - -The docstring in the file header should contain a link to the documentation to make it easy to find further information, especially about the configuration or details which are not mentioned in the code. - -```python -""" -Support for MQTT lights. - -For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/light.mqtt/ -""" -``` - -### Requirements - -Please place [Platform requirements](creating_platform_code_review.md#1-requirements) right after the imports. - -```python -[...] -from homeassistant.helpers.entity import Entity - -REQUIREMENTS = ['xmltodict==0.11.0'] -``` - -### Log messages - -There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. Try to avoid brackets and additional quotes around the output to make it easier for users to parse the log. A widely style is shown below but you are free to compose the messages as you like. - -```python -_LOGGER.error("No route to device: %s", self._resource) -``` - -```bash -2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18 -``` - -Don't print out wrong API keys, tokens, usernames, or passwords. -Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` in anything else. - -### Ordering of imports - -Instead of order the imports manually, use [`isort`](https://github.com/timothycrosley/isort). - -```bash -$ pip3 install isort -$ isort homeassistant/components/sensor/fixer.py -``` diff --git a/website/versioned_docs/version-0.73.0/documentation_create_page.md b/website/versioned_docs/version-0.73.0/documentation_create_page.md deleted file mode 100644 index a2d42141..00000000 --- a/website/versioned_docs/version-0.73.0/documentation_create_page.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Create a new page -id: version-0.73.0-documentation_create_page -original_id: documentation_create_page ---- - -For a platform or component page, the fastest way is to make a copy of an existing page and edit it. The [Component overview](https://www.home-assistant.io/components/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages. - -Please honor the [Standards](documentation_standards.md) we have for the documentation. - -If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers. - -```text ---- -layout: page -title: "Awesome Sensor" -description: "home-assistant.io web presence" -date: 2015-06-17 08:00 -sidebar: true -comments: false -sharing: true -footer: true -ha_release: "0.38" -ha_category: Sensor ---- - -Content...Written in markdown. - -### {% linkable_title Linkable Header %} -... -``` - -There are [pre-definied variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation. - -A couple of points to remember: - -- Document the needed steps to retrieve API keys or access token for the third party service or device if needed. -- If you're adding a new component, for the `ha_release` part of the header, just increment of the current release. If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`. -- `ha_category:` is needed to list the platform or component in the appropriate category on the website. - -### Configuration - -Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file. - -The **Configuration Variables** section must use the {% raw %}`{% configuration %} ... {% endconfiguration %}`{% endraw %} tag. - -```text -{% configuration %} -api_key: - description: The API key to access the service. - required: true - type: string -name: - description: Name to use in the frontend. - required: false - default: The default name to use in the frontend. - type: string -monitored_conditions: - description: Conditions to display in the frontend. - required: true - type: list - keys: - weather: - description: A human-readable text summary. - temperature: - description: The current temperature. -{% endconfiguration %} - -``` - -Available keys: - -- **`description:`**: That the variable is about. -- **`required:`**: If the variable is required. - -```text -required: true #=> Required -required: false #=> Optional -required: inclusive #=> Inclusive -required: exclusive #=> Exclusive -required: any string here #=> Any string here -``` -- **`type:`**: The type of the variable. Allowed entries: `string`, `int`, `time`, `template` or `map`. For multiple possibilities use `[string, int]`. If you use `map` then you need to define `keys:` (see the [`template` sensor](/components/sensor.template/) for an example). -- **`default:`**: The default value for the variable. - -### Embedding Code - -You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in {% raw %}`{% endraw %}. - -When you're writing code that is to be executed on the terminal, prefix it with `$`. - -### Templates - -For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) is [Jinja](http://jinja.pocoo.org/) used. Check the [Documentation Standards](documentation_standards.md) for further details. - -If you are don't escape templates then they will be rendered and appear blank on the website. - -### HTML - -The direct usage of HTML is supported but not recommended. The note boxes are an exception. - -```html -

- You need to enable telnet on your router. -

-``` - -### Images, icons and logos - -The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent. - -| Type | Location | -| :----------- |:----------------------------------------------| -| logos | source/images/supported_brands | -| blog | source/images/blog | -| screenshots | source/images/components | - -Not everything (product, component, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/). - -### Linking From The Sidebar - -If you are adding a new page that requires linking from the sidebar you need to edit the `docs_navigation.html` file in `home-assistant.github.io/source/_includes/asides/docs_navigation.html`. diff --git a/website/versioned_docs/version-0.73.0/documentation_index.md b/website/versioned_docs/version-0.73.0/documentation_index.md deleted file mode 100644 index 283543f4..00000000 --- a/website/versioned_docs/version-0.73.0/documentation_index.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Documentation -id: version-0.73.0-documentation_index -original_id: documentation_index ---- - -The user documentation is located at [https://www.home-assistant.io](https://www.home-assistant.io). This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know about HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process for working on the website is no different from working on Home Assistant itself. You work on your change and propose it via a Pull Request (PR). - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.3.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` -- In your home-assistant.github.io root directory, run `$ bundle` to install the gems you need. - -Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` - -Then you can work on the documentation: - -- Fork home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.github.io). -- Create/edit/update a page in the directory `source/_components/` for your platform/component. -- Test your changes to home-assistant.io locally: run `rake preview` and navigate to [http://127.0.0.1:4000](http://127.0.0.1:4000) -- Create a Pull Request (PR) against the **next** branch of home-assistant.github.io if your documentation is a new feature, platform, or component. -- Create a Pull Request (PR) against the **current** branch of home-assistant.github.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -It could be necessary that you run `rake generate` prior to `rake preview` for the very first preview. - -Site generated by `rake` is only available locally. If you are developing on a headless machine use port forwarding: - -```bash -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` - diff --git a/website/versioned_docs/version-0.73.0/documentation_standards.md b/website/versioned_docs/version-0.73.0/documentation_standards.md deleted file mode 100644 index 7f4be676..00000000 --- a/website/versioned_docs/version-0.73.0/documentation_standards.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Standards -id: version-0.73.0-documentation_standards -original_id: documentation_standards ---- - -To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation. - -## General Documentation - -* The language of the documentation should be American-English. -* Don't put two spaces after a period and avoid the "Oxford comma". -* Be objective and not gender favoring, polarizing, race related or religion inconsiderate. -* The case of brand names, services, protocols, components, and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select". -* All headings should use the `{% linkable_title %}` tag. - -## Component and Platform Pages - -* The **Configuration Variables** section must use the `{% configuration %}` tag. -* Configuration variables must document the requirement status. -* Configuration variables must document the default value, if any. -* Configuration variables must document the accepted value types. - * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`). -* Use YAML sequence syntax in the sample code if it is supported. -* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated. - * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`. - * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note. -* Component and platform names should be a link to their respective documentation pages. - -## Templates - -* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the `{% raw %}` tag. -* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`. -* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)): - * `friendly_name` - * Single-line templates: - * `value_template` - * `level_template` - * `icon_template` - * Children of `data_template` -* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks): - * Strings inside of templates: - * States - * Entity IDs - * `unit_of_measurement` -* No whitespace around pipe character (`|`) for Jinja2 filters. -* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}). -* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}). -* Do not quote values for: - * `device_class` - * `platform` - * `condition` - * `service` - -## Renaming Pages - -It can happen that a component or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old component/platform name, to the page in a [note](/developers/documentation/create_page/#html). - -```text ---- -... -redirect_from: /getting-started/android/ ---- -``` - -Adding a redirect also applies if you move content around in the [documentation](/docs/). - -## Single vs. Double Quotation Marks - -Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required). - -### Examples - -#### {% linkable_title Double Quotes Outside, Single Quotes Inside (Valid) %} - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}" -``` - -#### Single Quotes Outside, Double Quotes Inside (Invalid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}' -``` - -#### Multi-Line Template (Valid) - - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: >- - {% if trigger.to_state.name == 'Dale\'s Bedroom' %} - Someone's in your base, killing your noobs! - {% else %} - It's just another door. - {% endif %} -``` - diff --git a/website/versioned_docs/version-0.73.0/frontend_development.md b/website/versioned_docs/version-0.73.0/frontend_development.md deleted file mode 100644 index 14c9d0a5..00000000 --- a/website/versioned_docs/version-0.73.0/frontend_development.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Frontend development -sidebar_label: Development -id: version-0.73.0-frontend_development -original_id: frontend_development ---- - -The Home Assistant frontend is built using web components and powered by the [Polymer](https://www.polymer-project.org/) framework. - -> Do not use development mode in production. Home Assistant uses aggressive caching to improve the mobile experience. This is disabled during development so that you do not have to restart the server in between changes. - -## Setting up the environment - -> All commands below need to be run from inside the home-assistant-polymer repository. - -### Getting the code - -First step is to git clone the [home-assistant-polymer repository][hass-polymer]. You can place the repository anywhere on your system. - -```bash -$ git clone https://github.com/home-assistant/home-assistant-polymer.git -$ cd home-assistant-polymer -``` - -### Configuring Home Assistant - -Next step is to configure Home Assistant to use the development mode for the frontend. Do this by updating the frontend config in your `configuration.yaml` and set the path to the home-assistant-polymer repository that you cloned in the last step: - -```yaml -frontend: - # Example absolute path: /home/paulus/dev/hass/home-assistant-polymer - development_repo: -``` - -### Installing Node.js - -Node.js is required to build the frontend. The preferred method of installing node.js is with [nvm](https://github.com/creationix/nvm). Install nvm using the instructions in the [README](https://github.com/creationix/nvm#install-script), and install the correct node.js by running the following command: - -```bash -$ nvm install -``` - -[Yarn](https://yarnpkg.com/en/) is used as the package manager for node modules. [Install yarn using the instructions here.](https://yarnpkg.com/en/docs/install) - -Next, development dependencies need to be installed to bootstrap the frontend development environment. First activate the right Node version and then download all the dependencies: - -```bash -$ nvm use -$ script/bootstrap -``` - -## Development - -During development, you will need to run the development script to maintain a development build of the frontend that auto updates when you change any of the source files. To run this server, run: - -```bash -$ nvm use -$ script/develop -``` - -Make sure you have cache disabled and correct settings to avoid stale content: - -> Instructions are for Google Chrome - -1. Disable cache by ticking the box in `Network` > `Disable cache` - -

- -

- -2. Enable Bypass for network in `Application` > `Service Workers` > `Bypass for network` - -

- -

- -## Creating pull requests - -If you're planning on issuing a PR back to the Home Assistant codebase you need to fork the polymer project and add your fork as a remote to the Home Assistant Polymer repo. - -```bash -$ git remote add fork -``` - -When you've made your changes and are ready to push them change to the working directory for the polymer project and then push your changes - -``` bash -$ git add -A -$ git commit -m "Added new feature X" -$ git push -u fork HEAD -``` - -## Building the Polymer frontend - -If you're making changes to the way the frontend is packaged, it might be necessary to try out a new packaged build of the frontend in the main repository (instead of pointing it at the frontend repo). To do so, first build a production version of the frontend by running `script/build_frontend`. - -To test it out inside Home assistant, run the following command from the main Home Assistant repository: - -```bash -$ pip3 install -e /path/to/home-assistant-polymer/ -$ hass --skip-pip -``` - -[hass-polymer]: https://github.com/home-assistant/home-assistant-polymer diff --git a/website/versioned_docs/version-0.73.0/hassio_addon_config.md b/website/versioned_docs/version-0.73.0/hassio_addon_config.md deleted file mode 100644 index 4fccd138..00000000 --- a/website/versioned_docs/version-0.73.0/hassio_addon_config.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.73.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use `jq` inside your shell script to parse this data. However, you might have to install `jq` as a separate package in your container (see `Dockerfile` below). - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -## Add-on Docker file - -All add-ons are based on Alpine Linux 3.6. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | no | List of supported arch: `armhf`, `aarch64`, `amd64`, `i386`. Default all. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE` -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. diff --git a/website/versioned_docs/version-0.73.0/lovelace_custom_card.md b/website/versioned_docs/version-0.73.0/lovelace_custom_card.md deleted file mode 100644 index 22bf6169..00000000 --- a/website/versioned_docs/version-0.73.0/lovelace_custom_card.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -title: Custom Cards -id: version-0.73.0-lovelace_custom_card -original_id: lovelace_custom_card ---- - -You're not just limited to the cards that we decided to include in the Lovelace UI. You can build and use your own! - -## API - -You define your custom card as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). It's up to you to decide how to render your DOM inside your element. You can use Polymer, Angular, Preact or any other popular framework (except for React – [more info here](https://custom-elements-everywhere.com/)). - -```js -const element = document.createElement('some-custom-card'); -``` - -Home Assistant will call `setConfig(config)` when the configuration changes (rare). If you throw an exception if the configuration is invalid, an error card will render to notify the user. - -```js -try { - element.setConfig(config); -} catch (err) { - showErrorCard(err.message, config); -} -``` - -Home Assistant will set the `hass` property when the state of Home Assistant changes (frequent). Whenever the state changes, the component will have to update itself to represent the latest state. - -```js -element.hass = hass; -``` - -Your card can define a `getCardSize` method that returns the size of your card as a number. A height of 1 is equivalent to 50 pixels. This will help Home Assistant distribute the cards evenly over the columns. A card size of `1` will be assumed if the method is not defined. - -```js -if ('getCardSize' in element) { - return element.getCardSize(); -} else { - return 1; -} -``` - -## Defining your card - -Create a new file in your Home Assistant config dir as `/www/content-card-example.js` and put in the following contents: - -```js -class ContentCardExample extends HTMLElement { - set hass(hass) { - if (!this.content) { - const card = document.createElement('ha-card'); - card.header = 'Example card'; - this.content = document.createElement('div'); - this.content.style.padding = '0 16px 16px'; - card.appendChild(this.content); - this.appendChild(card); - } - - const entityId = this.config.entity; - const state = hass.states[entityId]; - const stateStr = state ? state.state : 'unavailable'; - - this.content.innerHTML = ` - The state of ${entityId} is ${stateStr}! -

- - `; - } - - setConfig(config) { - if (!config.entity) { - throw new Error('You need to define an entity'); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return 3; - } -} - -customElements.define('content-card-example', ContentCardExample); -``` - -## Referencing your new card - -In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `/www` directory, it will be accessible in your browser via the url `/local/`. - -```yaml -# Example ui-lovelace.yaml -resources: - - url: /local/content-card-example.js - type: js -views: -- name: Example - cards: - - type: "custom:content-card-example" - entity: input_boolean.switch_tv -``` - -## Advanced example - -Resources to load in Lovelace can be imported as a JS script, an HTML import or as a JS module import. Below is an example of a custom card using JS modules that does all the fancy things. - -![Screenshot of the wired card](/img/en/frontend/lovelace-ui-custom-card-screenshot.png) - -Create a new file in your Home Assistant config dir as `/www/wired-cards.js` and put in the following contents: - -```js -import 'https://unpkg.com/wired-card@0.6.5/wired-card.js?module'; -import 'https://unpkg.com/wired-toggle@0.6.5/wired-toggle.js?module'; -import { - LitElement, html -} from 'https://unpkg.com/@polymer/lit-element@^0.5.2/lit-element.js?module'; - -function loadCSS(url) { - const link = document.createElement('link'); - link.type = 'text/css'; - link.rel = 'stylesheet'; - link.href = url; - document.head.appendChild(link); -} - -loadCSS('https://fonts.googleapis.com/css?family=Gloria+Hallelujah'); - -class WiredToggleCard extends LitElement { - static get properties() { - return { - hass: Object, - config: Object, - } - } - - _render({ hass, config }) { - return html` - - - ${config.entities.map(ent => hass.states[ent]).map((state) => - html` -
- ${state.attributes.friendly_name} - -
- ` - )} -
- `; - } - - setConfig(config) { - if (!config.entities) { - throw new Error('You need to define entities'); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return this.config.entities.length + 1; - } - - _toggle(state) { - this.hass.callService('homeassistant', 'toggle', { - entity_id: state.entity_id - }); - } -} -customElements.define('wired-toggle-card', WiredToggleCard); -``` - -And for your configuration: - -```yaml -# Example ui-lovelace.yaml -resources: - - url: /local/wired-cards.js - type: module -views: -- name: Example - cards: - - type: "custom:wired-toggle-card" - entities: - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_livingroom - - input_boolean.switch_tv -``` diff --git a/website/versioned_docs/version-0.73.0/lovelace_index.md b/website/versioned_docs/version-0.73.0/lovelace_index.md deleted file mode 100644 index 55a28207..00000000 --- a/website/versioned_docs/version-0.73.0/lovelace_index.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Lovelace UI -sidebar_label: Introduction -id: version-0.73.0-lovelace_index -original_id: lovelace_index ---- - -This page has been moved to https://www.home-assistant.io/lovelace/ - - diff --git a/website/versioned_docs/version-0.74.0/asyncio_working_with_async.md b/website/versioned_docs/version-0.74.0/asyncio_working_with_async.md deleted file mode 100644 index 812c296a..00000000 --- a/website/versioned_docs/version-0.74.0/asyncio_working_with_async.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: Working with Async -id: version-0.74.0-asyncio_working_with_async -original_id: asyncio_working_with_async ---- - -Although we have a backwards compatible API, using the async core directly will be a lot faster. Most core components have already been rewritten to leverage the async core. This includes the EntityComponent helper (foundation of light, switch, etc), scripts, groups and automation. - -## Interacting with the core - -[All methods in the Home Assistant core][dev-docs] are implemented in two flavors: an async version and a version to be called from other threads. The versions for other are merely wrappers that call the async version in a threadsafe manner. - -So if you are making calls to the core (the hass object) from within a callback or coroutine, use the methods that start with async_. If you need to call an async_ function that is a coroutine, your task must also be a coroutine. - -## Implementing an async component - -To make a component async, implement an async_setup. - -```python -def setup(hass, config): - # Setup your component outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup(hass, config): - # Setup your component inside of the event loop. -``` - -## Implementing an async platform - -For platforms we support async setup. Instead of setup_platform you need to have a coroutine async_setup_platform. - -```python -setup_platform(hass, config, add_entities, discovery_info=None): - # Setup your platform outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup_platform(hass, config, async_add_entities, - discovery_info=None): - # Setup your platform inside of the event loop -``` - -The only difference with the original parameters is that the `add_entities` function has been replaced by the async friendly callback `async_add_entities`. - -## Implementing an async entity - -You can make your entity async friendly by converting your update method to be async. This requires the dependency of your entities to also be async friendly! - -```python -class MyEntity(Entity): - def update(self): - """Retrieve latest state.""" - self._state = fetch_state() -``` - -Will turn into: - -```python -class MyEntity(Entity): - async def async_update(self): - """Retrieve latest state.""" - self._state = await async_fetch_state() -``` - -Make sure that all properties defined on your entity do not result in I/O being done. All data has to be fetched inside the update method and cached on the entity. This is because these properties are read from within the event loop and thus doing I/O will result in the core of Home Assistant waiting until your I/O is done. - -## Calling async functions from threads - -Sometimes it will happen that you’re in a thread and you want to call a function that is only available as async. Home Assistant includes a few async helper utilities to help with this. - -In the following example, `say_hello` will schedule `async_say_hello` and block till the function has run and get the result back. - -```python -from homeassistant.util.async_ import run_callback_threadsafe - -def say_hello(hass, target): - return run_callback_threadsafe( - hass.loop, async_say_hello, target).result() - -async def async_say_hello(hass, target): - return "Hello {}!".format(target) -``` - -## Calling sync functions from async - -If you are running inside an async context, it might sometimes be necessary to call a sync function. Do this like this: - -```python -# hub.update() is a sync function. -result = await hass.async_add_executor_job(hub.update) -``` - -## Starting independent task from async - -If you want to spawn a task that will not block the current async context, you can choose to create it as a task on the event loop. It will then be executed in parallel. - -```python -hass.async_create_task(async_say_hello(hass, target)) -``` - - -[dev-docs]: https://dev-docs.home-assistant.io/en/master/api/core.html -[dev-docs-async]: https://dev-docs.home-assistant.io/en/dev/api/util.html#module-homeassistant.util.async diff --git a/website/versioned_docs/version-0.74.0/auth_api.md b/website/versioned_docs/version-0.74.0/auth_api.md deleted file mode 100644 index 3c4970ac..00000000 --- a/website/versioned_docs/version-0.74.0/auth_api.md +++ /dev/null @@ -1,89 +0,0 @@ ---- -title: Authentication API -sidebar_label: API -id: version-0.74.0-auth_api -original_id: auth_api ---- - -> This is experimental. It is not persisted and is not yet intended for production. - -This page will describe the steps required to fetch an access token for a user and how to refresh it. We follow the OAuth 2 specification. - -## Requirements - -A client needs to be created inside Home Assistant before a client can request users to authorize it or fetch a new access token. The only way currently to create a client is programmatically: - -```python -client = await hass.auth.async_get_or_create_client( - 'Example client', - redirect_uris=['http://www.example.com/hass_callback'] -) -print(client.id) -``` - -## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) - - - The authorize url should contain `client_id`, `redirect_uri` and, if available, `client_secret` as query parameters. Example: `http://your-instance.com/auth/authorize?client_id=ABCDE&client_secret=QWERTY&redirect_uri=https%3A%2F%2Fexample.com%2Fhass_callback` - - The user will navigate to this link, log into Home Assistant and authorize the client. - - Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code as part of the query parameters. Example: https://example.com/hass_callback?code=12345 - - This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section). - - As specified in the OAuth 2 specification, it is possible to pass an optional state string to the authorize url using the `state` query parameter. This string will be added as query parameter to the redirect url. - -## Token - -The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. - -All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`. - -### Authorization code - -Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is: - -``` -grant_type=authorization_code&code=12345 -``` - -The return response will be an access and refresh token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "refresh_token": "IJKLMNOPQRST", - "token_type": "Bearer" -} -``` - -### Refresh token - -Use the grant type `refresh_token` to retrieve an access token using a refresh token. The request body is: - -``` -grant_type=refresh_token&refresh_token=QWERTY -``` - -The return response will be an access token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "token_type": "Bearer" -} -``` - -## Making authenticated requests - -Once you have an access token, you can make authenticated requests to the Home Assistant APIs. - -For the websocket connection, pass the access token in the [authentication message](https://developers.home-assistant.io/docs/en/external_api_websocket.html#authentication-phase). - -For HTTP requests, pass the token type and access token as the authorization header: - -``` -Authorization: Bearer ABCDEFGH -``` - -If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and the client should ask the user to authorize again. diff --git a/website/versioned_docs/version-0.74.0/entity_media_player.md b/website/versioned_docs/version-0.74.0/entity_media_player.md deleted file mode 100644 index 4780aff6..00000000 --- a/website/versioned_docs/version-0.74.0/entity_media_player.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Media Player Entity -sidebar_label: Media Player -id: version-0.74.0-entity_media_player -original_id: entity_media_player ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| sound_mode | string | None | The current sound mode of the media player -| sound_mode_list | list | None | Dynamic list of available sound modes (set by platform, empty means sound mode not supported) -| source | string | None | The currently selected input source for the media player. -| source_list | list | None | The list of possible input sources for the media player. (This list should contain human readable names, suitible for frontend display) - - -## Methods -### Select sound mode -Optional. Switch the sound mode of the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - def async_select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - -### Select source -Optional. Switch the selected input source for the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_source(self, source): - """Select input source.""" - - def async_select_source(self, source): - """Select input source.""" diff --git a/website/versioned_docs/version-0.74.0/entity_vacuum.md b/website/versioned_docs/version-0.74.0/entity_vacuum.md deleted file mode 100644 index 0c93858e..00000000 --- a/website/versioned_docs/version-0.74.0/entity_vacuum.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Vacuum Entity -sidebar_label: Vacuum -id: version-0.74.0-entity_vacuum -original_id: entity_vacuum ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| name | string | **Required** | Name of the device. -| state | string | **Required** | One of the states listed in the states section. -| battery_level | int | `none` | Current battery level. -| battery_icon | string | function | Battery icon to show in UI. -| cleaning_mode | string | `none` | The current cleaning mode. -| cleaning_mode_list | list | `NotImplementedError()`| List of available fan speeds and cleaning modes. -| error | string | **Required** with `STATE_ERROR` | An error message if the vacuum is in `STATE_ERROR`. - - -## States -| State | Description -| ----- | ----------- -| `STATE_CLEANING` | The vacuum is currently cleaning. -| `STATE_DOCKED` | The vacuum is currently docked, it is assumed that docked can also mean charging. -| `STATE_PAUSED` | The vacuum was cleaning but was paused without returning to the dock. -| `STATE_IDLE` | The vacuum is not paused, not docked and does not have any errors. -| `STATE_RETURNING` | The vacuum is done cleaning and is currently returning to the dock, but not yet docked. -| `STATE_ERROR` | The vacuum encountered an error while cleaning, the error can be specified as a property on the entity. - -## Methods - -### `turn_on` or `async_turn_on` -Turn the vacuum on and start cleaning. - -### `turn_off`or `async_turn_off` -Turn the vacuum off stopping the cleaning and returning home. - -### `return_to_base` or `async_return_to_base` -Set the vacuum cleaner to return to the dock. - -### `stop` or `async_stop` -Stop the vacuum cleaner, do not return to base. - -### `clean_spot` or `async_clean_spot` -Perform a spot clean-up. - -### `locate` or `async_locate` -Locate the vacuum cleaner. - -### `set_cleaning_mode` or `async_set_cleaning_mode` -Set the cleaning mode. - -### `send_command` or `async_send_command` -Send a command to a vacuum cleaner. diff --git a/website/versioned_docs/version-0.74.0/hassio_addon_tutorial.md b/website/versioned_docs/version-0.74.0/hassio_addon_tutorial.md deleted file mode 100644 index 83d7479e..00000000 --- a/website/versioned_docs/version-0.74.0/hassio_addon_tutorial.md +++ /dev/null @@ -1,180 +0,0 @@ ---- -title: Tutorial: Making your first add-on -id: version-0.74.0-hassio_addon_tutorial -original_id: hassio_addon_tutorial ---- - -So you've got Home Assistant going and you've been enjoying the built-in add-ons but you're missing this one application. Time to make your own add-on! In Hass.io 0.24 we introduced the option to have local add-ons be build on your device. This is great for developing new add-ons locally. - -To get started with developing add-ons, we first need access to where Hass.io looks for local add-ons. For this you can use the Samba add-on or the SSH add-on. - -For Samba, once you have enabled and started it, your Hass.io instance will show up in your local network tab and share a folder called "addons". This is the folder to store your custom add-ons. - -If you are on macOS and the folder is not showing up automatically, go to Finder and press CMD+K then enter 'smb://hassio.local' - -![Screenshot of Windows Explorer showing a folder on the Hass.io server](/img/en/hass.io/tutorial/samba.png) - -For SSH, you will have to install it. Before you can start it, you will have to have a private/public key pair and store your public key in the add-on config ([see docs for more info][ssh]). Once started, you can SSH to Hass.io and store your custom add-ons in "/addons". - -![Screenshot of Putty connected to Hass.io](/img/en/hass.io/tutorial/ssh.png) - -Once you have located your add-on directory, it's time to get started! - -[ssh]: https://www.home-assistant.io/addons/ssh/ - -## Step 1: The basics - - - Create a new directory called `hello_world` - - Inside that directory create three files. - -`Dockerfile`: -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -`config.json`: -```json -{ - "name": "Hello world", - "version": "1", - "slug": "hello_world", - "description": "My first real add-on!", - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {} -} -``` - -`run.sh`: -```bash -echo Hello world! -``` -Make sure your editor is using UNIX-like line breaks (LF), not Dos/Windows (CRLF). - -## Step 2: Installing and testing your add-on - -Now comes the fun part, time to open the Hass.io UI and install and run your add-on. - - - Open the Home Assistant frontend - - Go to the Hass.io panel - - On the top right click the shopping basket to go to the add-on store. - -![Screenshot of the Hass.io main panel](/img/en/hass.io/screenshots/main_panel_addon_store.png) - - - On the top right click the refresh button - - You should now see a new card called "Local" that lists your add-on! - -![Screenshot of the local repository card](/img/en/hass.io/screenshots/local_repository.png) - - - Click on your add-on to go to the add-on details page. - - Install your add-on - - Start your add-on - - Refresh the logs of your add-on, you should now see "Hello world!" in your logs. - -![Screenshot of the add-on logs](/img/en/hass.io/tutorial/addon_hello_world_logs.png) - -### I don't see my add-on?! - -Oops! You clicked refresh in the store and your add-on didn't show up. Or maybe you just updated an option, clicked refresh and saw your add-on disappear. - -When this happens, it means that your `config.json` is invalid. It's either invalid JSON or one of the specified options is incorrect. To see what went wrong, go to the Hass.io panel and in the supervisor card click on "View logs". This should bring you to a page with the logs of the supervisor. Scroll to the bottom and you should be able to find the validation error. - -Once you fixed the error, go to the add-on store and click refresh again. - -## Step 3: Hosting a server - -Until now we've been able to do some basic stuff, but it's not very useful yet. So let's take it one step further and host a server that we expose on a port. For this we're going to use the built-in HTTP server that comes with Python 3. - -To do this, we will need to update our files as follows: - - - `Dockerfile`: Install Python 3 - - `config.json`: Make the port from the container available on the host - - `run.sh`: Run the Python 3 command to start the HTTP server - -Add to your `Dockerfile` before `RUN`: - -``` -# Install requirements for add-on -RUN apk add --no-cache python3 - -# Python 3 HTTP Server serves the current working dir -# So let's set it to our add-on persistent data directory. -WORKDIR /data -``` - -Add "ports" to `config.json`. This will make TCP on port 8000 inside the container available on the host on port 8000. - -```json -{ - "name": "Hello world", - "version": "0.2", - "slug": "hello_world", - "description": "My first real add-on!", - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {}, - "ports": { - "8000/tcp": 8000 - } -} -``` - -Update `run.sh` to start the Python 3 server: - -``` -python3 -m http.server -``` - -## Step 4: Installing the update - -Since we updated the version number in our `config.json`, Home Assistant will show an update button when looking at the add-on details. You might have to refresh your browser or click the refresh button in the add-on store for it to show up. If you did not update the version number, you can also uninstall and install the add-on again. After installing the add-on again, make sure you start it. - -Now navigate to [http://hassio.local:8000](http://hassio.local:8000) to see our server in action! - -![Screenshot of the file index served by the add-on](/img/en/hass.io/tutorial/python3-http-server.png) - -## Bonus: Working with add-on options - -In the screenshot you've probably seen that our server only served up 1 file: `options.json`. This file contains the user configuration for this add-on. Because we specified an empty "config" and "schema" in our `config.json`, the file is currently empty. - -Let's see if we can get some data into that file! - -To do this, we need to specify the default options and a schema for the user to change the options. - -Change the options and schema entries in your `config.json` with the following: - -```json -{ - … - - "options": { - "beer": true, - "wine": true, - "liquor": false, - "name": "world", - "year": 2017 - }, - "schema": { - "beer": "bool", - "wine": "bool", - "liquor": "bool", - "name": "str", - "year": "int" - }, - - … -} -``` - -Refresh the add-on store and re-install your add-on. You will now see the options available in the add-on config screen. When you now go back to our Python 3 server and download `options.json`, you'll see the options you set. [Example of how options.json can be used inside `run.sh`](https://github.com/home-assistant/hassio-addons/blob/master/mosquitto/run.sh#L4-L6) diff --git a/website/versioned_docs/version-0.74.0/internationalization_index.md b/website/versioned_docs/version-0.74.0/internationalization_index.md deleted file mode 100644 index ae9ba41c..00000000 --- a/website/versioned_docs/version-0.74.0/internationalization_index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Internationalization -id: version-0.74.0-internationalization_index -original_id: internationalization_index ---- - -The Home Assistant internationalization project includes preparing platforms and the frontend for localization, as well as the actual translation of localized strings. - -Some components and platforms will have strings that need to be localized specifically for that platform. These strings are managed in the core [home-assistant](https://github.com/home-assistant/home-assistant) repository. The Home Assistant backend will serve strings to the clients based on the loaded components in the running instance. - -There are also localizable strings that exist only on the frontend. These strings are managed in the [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer) repository. These strings are stored with the frontend and don’t depend on the backend configuration. - -Our strings are translated by the community using the online translation tool [Lokalise](https://lokalise.co/). diff --git a/website/versioned_docs/version-0.74.0/lovelace_custom_card.md b/website/versioned_docs/version-0.74.0/lovelace_custom_card.md deleted file mode 100644 index 2b11c6b7..00000000 --- a/website/versioned_docs/version-0.74.0/lovelace_custom_card.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -title: Lovelace: Custom Cards -id: version-0.74.0-lovelace_custom_card -original_id: lovelace_custom_card ---- - -[Lovelace](https://www.home-assistant.io/lovelace/) is our new approach to defining your user interface for Home Assistant. We offer a lot of built-in cards, but you're not just limited to the ones that we decided to include in the Lovelace UI. You can build and use your own! - -## API - -You define your custom card as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). It's up to you to decide how to render your DOM inside your element. You can use Polymer, Angular, Preact or any other popular framework (except for React – [more info on React here](https://custom-elements-everywhere.com/#react)). - -```js -const element = document.createElement('some-custom-card'); -``` - -Home Assistant will call `setConfig(config)` when the configuration changes (rare). If you throw an exception if the configuration is invalid, Lovelace will render an error card to notify the user. - -```js -try { - element.setConfig(config); -} catch (err) { - showErrorCard(err.message, config); -} -``` - -Home Assistant will set the `hass` property when the state of Home Assistant changes (frequent). Whenever the state changes, the component will have to update itself to represent the latest state. - -```js -element.hass = hass; -``` - -Your card can define a `getCardSize` method that returns the size of your card as a number. A height of 1 is equivalent to 50 pixels. This will help Home Assistant distribute the cards evenly over the columns. A card size of `1` will be assumed if the method is not defined. - -```js -if ('getCardSize' in element) { - return element.getCardSize(); -} else { - return 1; -} -``` - -## Defining your card - -Create a new file in your Home Assistant config dir as `/www/content-card-example.js` and put in the following contents: - -```js -class ContentCardExample extends HTMLElement { - set hass(hass) { - if (!this.content) { - const card = document.createElement('ha-card'); - card.header = 'Example card'; - this.content = document.createElement('div'); - this.content.style.padding = '0 16px 16px'; - card.appendChild(this.content); - this.appendChild(card); - } - - const entityId = this.config.entity; - const state = hass.states[entityId]; - const stateStr = state ? state.state : 'unavailable'; - - this.content.innerHTML = ` - The state of ${entityId} is ${stateStr}! -

- - `; - } - - setConfig(config) { - if (!config.entity) { - throw new Error('You need to define an entity'); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return 3; - } -} - -customElements.define('content-card-example', ContentCardExample); -``` - -## Referencing your new card - -In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `/www` directory, it will be accessible in your browser via the url `/local/`. - -```yaml -# Example ui-lovelace.yaml -resources: - - url: /local/content-card-example.js - type: js -views: -- name: Example - cards: - - type: "custom:content-card-example" - entity: input_boolean.switch_tv -``` - -## Advanced example - -Resources to load in Lovelace can be imported as a JS script, an HTML import or as a JS module import. Below is an example of a custom card using JS modules that does all the fancy things. - -![Screenshot of the wired card](/img/en/frontend/lovelace-ui-custom-card-screenshot.png) - -Create a new file in your Home Assistant config dir as `/www/wired-cards.js` and put in the following contents: - -```js -import 'https://unpkg.com/wired-card@0.6.5/wired-card.js?module'; -import 'https://unpkg.com/wired-toggle@0.6.5/wired-toggle.js?module'; -import { - LitElement, html -} from 'https://unpkg.com/@polymer/lit-element@^0.5.2/lit-element.js?module'; - -function loadCSS(url) { - const link = document.createElement('link'); - link.type = 'text/css'; - link.rel = 'stylesheet'; - link.href = url; - document.head.appendChild(link); -} - -loadCSS('https://fonts.googleapis.com/css?family=Gloria+Hallelujah'); - -class WiredToggleCard extends LitElement { - static get properties() { - return { - hass: Object, - config: Object, - } - } - - _render({ hass, config }) { - return html` - - - ${config.entities.map(ent => hass.states[ent]).map((state) => - html` -
- ${state.attributes.friendly_name} - -
- ` - )} -
- `; - } - - setConfig(config) { - if (!config.entities) { - throw new Error('You need to define entities'); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return this.config.entities.length + 1; - } - - _toggle(state) { - this.hass.callService('homeassistant', 'toggle', { - entity_id: state.entity_id - }); - } -} -customElements.define('wired-toggle-card', WiredToggleCard); -``` - -And for your configuration: - -```yaml -# Example ui-lovelace.yaml -resources: - - url: /local/wired-cards.js - type: module -views: -- name: Example - cards: - - type: "custom:wired-toggle-card" - entities: - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_livingroom - - input_boolean.switch_tv -``` diff --git a/website/versioned_docs/version-0.76.0/auth_api.md b/website/versioned_docs/version-0.76.0/auth_api.md deleted file mode 100644 index 36ae3a05..00000000 --- a/website/versioned_docs/version-0.76.0/auth_api.md +++ /dev/null @@ -1,128 +0,0 @@ ---- -title: Authentication API -sidebar_label: API -id: version-0.76.0-auth_api -original_id: auth_api ---- - -This page will describe the steps required for your application to authorize against and integrate with Home Assistant instances. - -Each user has their own instance of Home Assistant which gives each user control over their own data. However, we also wanted to make it easy for third party developers to create applications that allow users to integrate with Home Assistant. To achieve this, we have adopted the [OAuth 2 specification][oauth2-spec] combined with the [OAuth 2 IndieAuth extension][indieauth-spec] for generating clients. - -## Clients - -Before you can ask the user to authorize their instance with your application, you will need a client. In traditional OAuth2, the server needs to generate a client before a user can authorize. However, as each server belongs to a user, we've adopted a slightly different approach from [IndieAuth][indieauth-clients]. - -The client ID you need to use is the website of your application. The redirect url has to be of the same host and port as the client ID. For example: - - - client id: `https://www.my-application.io` - - redirect uri: `https://www.my-application.io/hass/auth_callback` - -If you require a different redirect url (ie, if building a native app), you can add an HTML tag to the content of the website of your application (the client ID) with an approved redirect url. For example: - -```html - -``` - -Home Assistant will scan the first 10kB of a website for these tags. - -## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) - -> All example URLs here are shown with extra spaces and new lines for clarity. Those should not be in the final url. - -The authorize url should contain `client_id` and `redirect_uri` as query parameters. - -``` -http://your-instance.com/auth/authorize? - client_id=ABCDE& - redirect_uri=https%3A%2F%2Fexample.com%2Fhass_callback -``` - -Optionally you can also include a `state` parameter, this will be added to the redirect uri. The state is perfect to store the instance url that you are authenticating with. Example: - -``` -http://your-instance.com/auth/authorize? - client_id=ABCDE& - redirect_uri=https%3A%2F%2Fexample.com%2Fhass_callback& - state=http%3A%2F%2Fhassio.local%3A8123 -``` - -The user will navigate to this link and be presented with instructions to log in and authorize your application. Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code and state as part of the query parameters. Example: - -``` -https://example.com/hass_callback? - code=12345& - state=http%3A%2F%2Fhassio.local%3A8123 -``` - -This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section). - -## Token - -The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. - -All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`. - -### Authorization code - -> All requests to the token endpoint need to contain the exact same client ID as was used to redirect the user to the authorize endpoint. - -Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is: - -``` -grant_type=authorization_code& -code=12345& -client_id=https%3A%2F%2Fwww.home-assistant.io%2Fios -``` - -The return response will be an access and refresh token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "refresh_token": "IJKLMNOPQRST", - "token_type": "Bearer" -} -``` - -The access token is a short lived token that can be used to access the API. The refresh token can be used to fetch new access tokens. The `expires_in` value is seconds that the access token is valid. - -### Refresh token - -Once you have retrieved a refresh token via the grant type `authorization_code`, you can use it to fetch new access tokens. The request body is: - -``` -grant_type=refresh_token& -refresh_token=IJKLMNOPQRST -``` - -The return response will be an access token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "token_type": "Bearer" -} -``` - -## Making authenticated requests - -Once you have an access token, you can make authenticated requests to the Home Assistant APIs. - -For the websocket connection, pass the access token in the [authentication message](https://developers.home-assistant.io/docs/en/external_api_websocket.html#authentication-phase). - -For HTTP requests, pass the token type and access token as the authorization header: - -``` -Authorization: Bearer ABCDEFGH -``` - -If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and so the user is no longer logged in. You should clear the user's data and ask the user to authorize again. - -[oauth2-spec]: https://tools.ietf.org/html/rfc6749 -[indieauth-spec]: https://indieauth.spec.indieweb.org/ -[indieauth-clients]: https://indieauth.spec.indieweb.org/#client-identifier diff --git a/website/versioned_docs/version-0.76.0/auth_auth_provider.md b/website/versioned_docs/version-0.76.0/auth_auth_provider.md deleted file mode 100644 index a19bc21d..00000000 --- a/website/versioned_docs/version-0.76.0/auth_auth_provider.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -title: Authentication Providers -id: version-0.76.0-auth_auth_provider -original_id: auth_auth_provider ---- - -Authentication providers confirm the identity of users. The user proofs their identity by going through the login flow for an auth provider. The auth provider defines the login flow and can ask the user all information this needs. This will commonly be username and password but could also include a 2FA token or other challenges. - -Once an authentication provider has confirmed the identity of a user, it will pass that on to Home Assistant in the form of a Credentials object. - -## Defining an auth provider - -> We currently only support built-in auth providers. Support for custom auth providers might arrive in the future. - -Auth providers are defined in `homeassistant/auth_providers/.py`. The auth provider module will need to provide an implementation of the `AuthProvider` class and contain a credential flow. This flow is what asks user for information and validates it. - -For an example of a fully implemented auth provider, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/providers/insecure_example.py). - -Auth providers can extend the following methods. - -| method | Required | Description -| ------ | -------- | ----------- -| async def async_credential_flow(self) | Yes | Return an instance of the credential flow for a user to identify itself. -| async def async_get_or_create_credentials(self, flow_result) | Yes | Given the result of a credential flow, return a credentials object. This can either be an existing one or a new one. -| async def async_initialize(self) | No | Callback callled once before interacting with the auth provider for the first time. -| async def async_user_meta_for_credentials(credentials) | No | Callback called Home Assistant is going to create a user from a Credentials object. Can be used to populate extra fields for the user. diff --git a/website/versioned_docs/version-0.76.0/development_environment.md b/website/versioned_docs/version-0.76.0/development_environment.md deleted file mode 100644 index 42e60d9e..00000000 --- a/website/versioned_docs/version-0.76.0/development_environment.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.76.0-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example Centos would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -If you are using Windows as a development platform, make sure that you have the correct Microsoft [Visual C++ build tools](http://landinghub.visualstudio.com/visual-cpp-build-tools) installed. The installation of the most requirements and validation using `tox` will fail if this is not done correctly. Check the [Windows Compilers](https://wiki.python.org/moin/WindowsCompilers) section on the [Python website](https://www.python.org/) for details. - -Due to Home Assistant is mainly designed and developed on Linux distributions it is not recommended to develop on Windows machines. However on Windows 10 machines you should decide to set up a [Linux subsystem](https://docs.microsoft.com/de-de/windows/wsl/install-win10). - -Setup Linux subsystem. - -```bash -$ sudo apt-get update -$ sudo apt-get upgrade -$ echo 'export DISPLAY=:0' >> ~/.bashrc && . ~/.bashrc -$ sudo apt-get install xubuntu-desktop -y -``` - -It is recommended using [PyCharm](https://www.jetbrains.com/pycharm/download/) as debugger. Download and start PyCharm. - -```bash -$ wget https://download.jetbrains.com/python/pycharm-community-20XX.X.tar.gz -$ tar -xzf pycharm-community-20XX.X -$ ./pycharm.sh -``` - -In order to display the PyCharm GUI on Windows you need to run a X-Server like [VcXserv](https://sourceforge.net/projects/vcxsrv/). - -Also, make sure to install or upgrade the `setuptools` Python package. It contains compatibility improvements and adds automatic use of compilers: - -```bash -$ pip install --upgrade setuptools -``` - -### Developing on OS X - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 -``` - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv . -$ source bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation. - -```bash -$ hass -``` - -## Logging - -By default logging in home-assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on. diff --git a/website/versioned_docs/version-0.76.0/documentation_create_page.md b/website/versioned_docs/version-0.76.0/documentation_create_page.md deleted file mode 100644 index 1cd6c7d7..00000000 --- a/website/versioned_docs/version-0.76.0/documentation_create_page.md +++ /dev/null @@ -1,121 +0,0 @@ ---- -title: Create a new page -id: version-0.76.0-documentation_create_page -original_id: documentation_create_page ---- - -For a platform or component page, the fastest way is to make a copy of an existing page and edit it. The [Component overview](https://www.home-assistant.io/components/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages. - -Please honor the [Standards](documentation_standards.md) we have for the documentation. - -If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers. - -```text ---- -layout: page -title: "Awesome Sensor" -description: "home-assistant.io web presence" -date: 2015-06-17 08:00 -sidebar: true -comments: false -sharing: true -footer: true -ha_release: "0.38" -ha_category: Sensor ---- - -Content...Written in markdown. - -### {% linkable_title Linkable Header %} -... -``` - -There are [pre-definied variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation. - -A couple of points to remember: - -- Document the needed steps to retrieve API keys or access token for the third party service or device if needed. -- If you're adding a new component, for the `ha_release` part of the header, just increment of the current release. If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`. -- `ha_category:` is needed to list the platform or component in the appropriate category on the website. - -### Configuration - -Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file. - -The **Configuration Variables** section must use the `{% configuration %} ... {% endconfiguration %}` tag. - -```text -{% configuration %} -api_key: - description: The API key to access the service. - required: true - type: string -name: - description: Name to use in the frontend. - required: false - default: The default name to use in the frontend. - type: string -monitored_conditions: - description: Conditions to display in the frontend. - required: true - type: map - keys: - weather: - description: A human-readable text summary. - temperature: - description: The current temperature. -{% endconfiguration %} -``` - -Available keys: - -- **`description:`**: That the variable is about. -- **`required:`**: If the variable is required. - -```text -required: true #=> Required -required: false #=> Optional -required: inclusive #=> Inclusive -required: exclusive #=> Exclusive -required: any string here #=> Any string here -``` -- **`type:`**: The type of the variable. Allowed entries: `string`, `int`, `time`, `template` or `map` (for a list of entries). For multiple possibilities use `[string, int]`. If you use `map` then you need to define `keys:` (see the [`template` sensor](/components/sensor.template/) for an example). -- **`default:`**: The default value for the variable. - -### Embedding Code - -You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in back-ticks. - -When you're writing code that is to be executed on the terminal, prefix it with `$`. - -### Templates - -For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) is [Jinja](http://jinja.pocoo.org/) used. Check the [Documentation Standards](documentation_standards.md) for further details. - -If you are don't escape templates then they will be rendered and appear blank on the website. - -### HTML - -The direct usage of HTML is supported but not recommended. The note boxes are an exception. - -```html -

- You need to enable telnet on your router. -

-``` - -### Images, icons and logos - -The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent. - -| Type | Location | -| :----------- |:----------------------------------------------| -| logos | source/images/supported_brands | -| blog | source/images/blog | -| screenshots | source/images/components | - -Not everything (product, component, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/). - -### Linking From The Sidebar - -If you are adding a new page that requires linking from the sidebar you need to edit the `docs_navigation.html` file in `home-assistant.github.io/source/_includes/asides/docs_navigation.html`. diff --git a/website/versioned_docs/version-0.76.0/documentation_standards.md b/website/versioned_docs/version-0.76.0/documentation_standards.md deleted file mode 100644 index ad92319c..00000000 --- a/website/versioned_docs/version-0.76.0/documentation_standards.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Standards -id: version-0.76.0-documentation_standards -original_id: documentation_standards ---- - -To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation. - -## General Documentation - -* The language of the documentation should be American-English. -* Don't put two spaces after a period and avoid the "Oxford comma". -* There is no limit for the line length. You are allowed to write in a flowing text style. This will make it easier to use the GitHub online editor in the future. -* Be objective and not gender favoring, polarizing, race related or religion inconsiderate. -* The case of brand names, services, protocols, components, and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select". -* All headings should use the `{% linkable_title %}` tag. -* Do not use ALL CAPITALS for emphasis - use italics instead - -## Component and Platform Pages - -* The **Configuration Variables** section must use the `{% configuration %}` tag. -* Configuration variables must document the requirement status. -* Configuration variables must document the default value, if any. -* Configuration variables must document the accepted value types. - * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`). -* Use YAML sequence syntax in the sample code if it is supported. -* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated. - * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`. - * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note. -* Component and platform names should be a link to their respective documentation pages. - -## Templates - -* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the `{% raw %}` tag. -* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`. -* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)): - * `friendly_name` - * Single-line templates: - * `value_template` - * `level_template` - * `icon_template` - * Children of `data_template` -* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks): - * Strings inside of templates: - * States - * Entity IDs - * `unit_of_measurement` -* No whitespace around pipe character (`|`) for Jinja2 filters. -* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}). -* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}). -* Do not quote values for: - * `device_class` - * `platform` - * `condition` - * `service` - -## Renaming Pages - -It can happen that a component or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old component/platform name, to the page in a [note](/developers/documentation/create_page/#html). - -```text ---- -... -redirect_from: /getting-started/android/ ---- -``` - -Adding a redirect also applies if you move content around in the [documentation](/docs/). - -## Single vs. Double Quotation Marks - -Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required). - -### Examples - -#### {% linkable_title Double Quotes Outside, Single Quotes Inside (Valid) %} - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}" -``` - -#### Single Quotes Outside, Double Quotes Inside (Invalid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}' -``` - -#### Multi-Line Template (Valid) - - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: >- - {% if trigger.to_state.name == 'Dale\'s Bedroom' %} - Someone's in your base, killing your noobs! - {% else %} - It's just another door. - {% endif %} -``` - diff --git a/website/versioned_docs/version-0.76.0/frontend_creating_custom_panels.md b/website/versioned_docs/version-0.76.0/frontend_creating_custom_panels.md deleted file mode 100644 index 39d36ce3..00000000 --- a/website/versioned_docs/version-0.76.0/frontend_creating_custom_panels.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Creating custom panels -id: version-0.76.0-frontend_creating_custom_panels -original_id: frontend_creating_custom_panels ---- - -Panels are pages that show information within Home Assistant and can allow controlling it. Panels are linked from the sidebar and rendered full screen. They have real-time access to the Home Assistant object via JavaScript. Examples of panels in the app are Map, Logbook and History. - -Besides components registering panels, users can also register panels using the `panel_custom` component. This allows users to quickly build their own custom interfaces for Home Assistant. - -## Introduction - -Panels are defined as custom elements. You can use any framework that you want, as long as you wrap it up as a custom element. To quickly get started with a panel, we've created a [React custom panel starter kit](https://github.com/home-assistant/custom-panel-starter-kit-react). - -## API reference - -The Home Assistant frontend will pass information to your panel by setting properties on your custom element. The following properties are set: - -| Property | Type | Description -| -------- | ---- | ----------- -| hass | object | Current state of Home Assistant -| narrow | boolean | if the panel should render in narrow mode -| showMenu | boolean | if the sidebar is currently shown -| panel | object | Panel information. Config is available as `panel.config`. - -## JavaScript versions - -The Home Assistant user interface is currently served to browsers in modern JavaScript and older JavaScript (ES5). The older version has a wider browser support but that comes at a cost of size and performance. - -To keep things easy, we advice you to tell your users to force the modern version of the frontend. That way you won't need any build tools while developing your panel. Add this to your config: - -```yaml -# configuration.yaml example -frontend: - javascript_version: latest -``` - -If you do need to run with ES5 support, you will need to load the ES5 custom elements adapter before defining your element: - -```js -window.loadES5Adapter().then(function() { - customElements.define('my-panel', MyCustomPanel) -}); -``` diff --git a/website/versioned_docs/version-0.76.0/frontend_data.md b/website/versioned_docs/version-0.76.0/frontend_data.md deleted file mode 100644 index 52d6a9d8..00000000 --- a/website/versioned_docs/version-0.76.0/frontend_data.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: Frontend data -sidebar_label: Data -id: version-0.76.0-frontend_data -original_id: frontend_data ---- - -The frontend passes a single `hass` object around. This object contains the latest state and allows you to send commands back to the server. - -Whenever a state changes, a new version of the objects that changed are created. So you can easily see if something has changed by doing a strict equality check: - -```js -const changed = newVal !== oldVal; -``` - -## Data - -### `hass.states` - -An object containing the states of all entities in Home Assistant. The key is the entity_id, thte value is the state object. - -```json -{ - "sun.sun": { - "entity_id": "sun.sun", - "state": "above_horizon", - "attributes": { - "next_dawn": "2018-08-18T05:39:19+00:00", - "next_dusk": "2018-08-17T18:28:52+00:00", - "next_midnight": "2018-08-18T00:03:51+00:00", - "next_noon": "2018-08-18T12:03:58+00:00", - "next_rising": "2018-08-18T06:00:33+00:00", - "next_setting": "2018-08-17T18:07:37+00:00", - "elevation": 60.74, - "azimuth": 297.69, - "friendly_name": "Sun" - }, - "last_changed": "2018-08-17T13:46:59.083836+00:00", - "last_updated": "2018-08-17T13:49:30.378101+00:00", - "context": { - "id": "74c2b3b429c844f18e59669e4b41ec6f", - "user_id": null - }, - }, - "light.ceiling_lights": { - "entity_id": "light.ceiling_lights", - "state": "on", - "attributes": { - "min_mireds": 153, - "max_mireds": 500, - "brightness": 180, - "color_temp": 380, - "hs_color": [ - 56, - 86 - ], - "rgb_color": [ - 255, - 240, - 35 - ], - "xy_color": [ - 0.459, - 0.496 - ], - "white_value": 200, - "friendly_name": "Ceiling Lights", - "supported_features": 151 - }, - "last_changed": "2018-08-17T13:46:59.129248+00:00", - "last_updated": "2018-08-17T13:46:59.129248+00:00", - "context": { - "id": "2c6bbbbb66a84a9dae097b6ed6c93383", - "user_id": null - }, - } -} -``` - -### `hass.user` - -The logged in user. - -```json -{ - "id": "758186e6a1854ee2896efbd593cb542c", - "name": "Paulus", - "is_owner": true, - "credentials": [ - { - "auth_provider_type": "homeassistant", - "auth_provider_id": null - } - ] -} -``` - -## Methods - -All method starting with `call` are async methods. This means that they will return a `Promise` that will resolve with the result of the call. - -### `hass.callService(domain, service, data)` - -Call a service on the backend. - -```js -hass.callService('light', 'turn_on', { - entity_id: 'light.kitchen' -}); -``` - -### `hass.callWS(message)` - -Call a WebSocket command on the backend. - -```js -this.hass.callWS({ - type: 'config/auth/create', - name: 'Paulus', -}).then(userResponse => - console.log("Created user", userResponse.user.id)); -``` - -### `hass.callApi(method, path, data)` - -Call an API on the Home Assistant server. For example, if you want to fetch all Hass.io snapshots by issuing a GET request to `/api/hassio/snapshots`: - -```js -hass.callApi('get', 'hassio/snapshots') - .then(snapshots => console.log('Received snapshots!', snapshots)); -``` - -If you need to pass in data, pass a third argument: - -```js -hass.callApi('delete', 'notify.html5', { subscription: 'abcdefgh' }); -``` - -_We're moving away from API calls and are migrating everything to `hass.callWS(message)` calls._ diff --git a/website/versioned_docs/version-0.76.0/hassio_addon_config.md b/website/versioned_docs/version-0.76.0/hassio_addon_config.md deleted file mode 100644 index fe42813f..00000000 --- a/website/versioned_docs/version-0.76.0/hassio_addon_config.md +++ /dev/null @@ -1,204 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.76.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use `jq` inside your shell script to parse this data. However, you might have to install `jq` as a separate package in your container (see `Dockerfile` below). - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -## Add-on Docker file - -All add-ons are based on Alpine Linux 3.6. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | no | List of supported arch: `armhf`, `aarch64`, `amd64`, `i386`. Default all. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `S40-DFS-P01` -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. diff --git a/website/versioned_docs/version-0.76.0/hassio_debugging.md b/website/versioned_docs/version-0.76.0/hassio_debugging.md deleted file mode 100644 index 51ea1577..00000000 --- a/website/versioned_docs/version-0.76.0/hassio_debugging.md +++ /dev/null @@ -1,49 +0,0 @@ ---- -title: Debugging Hass.io -id: version-0.76.0-hassio_debugging -original_id: hassio_debugging ---- - -> This section is not for users. Use the [SSH add-on] to SSH into Hass.io. This is for developers of Hass.io. Do not ask for support if you are using these options. - -[SSH add-on]: https://www.home-assistant.io/addons/ssh/ - -The following debug tips and tricks are for people who are running the Hass.io image and are working on the base image. If you use the generic Linux installer script, you should be able to access your host and logs as per your host. - -## SSH access to the host - -### resinOS based Hass.io (deprecated) -Create an `authorized_keys` file containing your public key, and place it in the root of the boot partition of your SD card. Once the device is booted, you can access your device as root over SSH on port 22222. - -### HassOS based Hass.io -Use a USB drive formatted with FAT, ext4, or NTFS and name it CONFIG (case sensitive). Create an `authorized_keys` file containing your public key, and place it in the root of the USB drive. From the UI, navigate to the hass.io system page and choose "Import from USB". You can now access your device as root over SSH on port 22222. Alternatively, the file will be imported from the USB when the hass.io device is rebooted. - -Windows instructions how to generate and use private/public keys with Putty are [here][windows-keys]. Instead of the droplet instructions, add the public key as per above instructions. - -Alternative instructions, for Mac, Windows and Linux can be found [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#platform-mac). - -Follow steps 1-4 under 'Generating a new SSH key' (The other sections are not applicable to Hass.io and can be ignored.) - -Step 3 in the link above, shows the path to the private key file `id_rsa` for your chosen operating system. Your public key, `id_rsa.pub`, is saved in the same folder. Next, select all text from text box "Public key for pasting into OpenSSH authorized_keys file" and save it to the root of your SD card as `authorized_keys`. - -> Make sure when you are copying the public key to the root of the /resin-boot partition of the SD card that you rename the file correctly to `authorized_keys` with no `.pub` file extension. - -You should then be able to SSH into your Hass.io device. On mac/linux, use: -``` -ssh root@hassio.local -p 22222 -``` - -## Checking the logs - -```bash -# Logs from the supervisor service on the Host OS -journalctl -f -u hassos-supervisor.service - -# Hass.io supervisor logs -docker logs hassos_supervisor - -# Home Assistant logs -docker logs homeassistant -``` - -[windows-keys]: https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-putty-on-digitalocean-droplets-windows-users diff --git a/website/versioned_docs/version-0.77.0/auth_api.md b/website/versioned_docs/version-0.77.0/auth_api.md deleted file mode 100644 index c291feed..00000000 --- a/website/versioned_docs/version-0.77.0/auth_api.md +++ /dev/null @@ -1,158 +0,0 @@ ---- -title: "Authentication API" -sidebar_label: API -id: version-0.77.0-auth_api -original_id: auth_api ---- - -This page will describe the steps required for your application to authorize against and integrate with Home Assistant instances. [See a demo](https://hass-auth-demo.glitch.me) powered by our helper lib [home-assistant-js-websocket](https://github.com/home-assistant/home-assistant-js-websocket). - -Each user has their own instance of Home Assistant which gives each user control over their own data. However, we also wanted to make it easy for third party developers to create applications that allow users to integrate with Home Assistant. To achieve this, we have adopted the [OAuth 2 specification][oauth2-spec] combined with the [OAuth 2 IndieAuth extension][indieauth-spec] for generating clients. - -## Clients - -Before you can ask the user to authorize their instance with your application, you will need a client. In traditional OAuth2, the server needs to generate a client before a user can authorize. However, as each server belongs to a user, we've adopted a slightly different approach from [IndieAuth][indieauth-clients]. - -The client ID you need to use is the website of your application. The redirect url has to be of the same host and port as the client ID. For example: - - - client id: `https://www.my-application.io` - - redirect uri: `https://www.my-application.io/hass/auth_callback` - -If you require a different redirect url (ie, if building a native app), you can add an HTML tag to the content of the website of your application (the client ID) with an approved redirect url. For example, add this to your site to whitelist redirect uri `hass://auth`: - -```html - -``` - -Home Assistant will scan the first 10kB of a website for link tags. - -## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) - -> All example URLs here are shown with extra spaces and new lines for display purposes only. - -The authorize url should contain `client_id` and `redirect_uri` as query parameters. - -``` -http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2F%3Fauth_callback%3D1 -``` - -Optionally you can also include a `state` parameter, this will be added to the redirect uri. The state is perfect to store the instance url that you are authenticating with. Example: - -``` -http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2Fauth_callback& - state=http%3A%2F%2Fhassio.local%3A8123 -``` - -The user will navigate to this link and be presented with instructions to log in and authorize your application. Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code and state as part of the query parameters. Example: - -``` -https://hass-auth-demo.glitch.me/auth_callback - code=12345& - state=http%3A%2F%2Fhassio.local%3A8123 -``` - -This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section). - -## Token - -The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. In thee case of refresh token, the token endpoint is also capable of revoking a token. - -All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`. - -### Authorization code - -> All requests to the token endpoint need to contain the exact same client ID as was used to redirect the user to the authorize endpoint. - -Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is: - -``` -grant_type=authorization_code& -code=12345& -client_id=https%3A%2F%2Fhass-auth-demo.glitch.me -``` - -The return response will be an access and refresh token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "refresh_token": "IJKLMNOPQRST", - "token_type": "Bearer" -} -``` - -The access token is a short lived token that can be used to access the API. The refresh token can be used to fetch new access tokens. The `expires_in` value is seconds that the access token is valid. - -An HTTP status code of 400 will be returned if an invalid request has been issued. The HTTP status code will be 403 if a token is requested for an inactive user. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Refresh token - -Once you have retrieved a refresh token via the grant type `authorization_code`, you can use it to fetch new access tokens. The request body is: - -``` -grant_type=refresh_token& -refresh_token=IJKLMNOPQRST& -client_id=https%3A%2F%2Fhass-auth-demo.glitch.me -``` - -The return response will be an access token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "token_type": "Bearer" -} -``` - -An HTTP status code of 400 will be returned if an invalid request has been issued. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Revoking a refresh token - -The token endpoint is also capable of revoking a refresh token. Revoking a refresh token will immediately revoke the refresh token and all access tokens that it has ever granted. To revoke a refresh token, make the following request: - -``` -token=IJKLMNOPQRST& -action=revoke -``` - -The request will always respond with an empty body and HTTP status 200, regardless if the request was successful. - -## Making authenticated requests - -Once you have an access token, you can make authenticated requests to the Home Assistant APIs. - -For the websocket connection, pass the access token in the [authentication message](https://developers.home-assistant.io/docs/en/external_api_websocket.html#authentication-phase). - -For HTTP requests, pass the token type and access token as the authorization header: - -``` -Authorization: Bearer ABCDEFGH -``` - -If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and so the user is no longer logged in. You should clear the user's data and ask the user to authorize again. - -[oauth2-spec]: https://tools.ietf.org/html/rfc6749 -[indieauth-spec]: https://indieauth.spec.indieweb.org/ -[indieauth-clients]: https://indieauth.spec.indieweb.org/#client-identifier diff --git a/website/versioned_docs/version-0.77.0/auth_auth_module.md b/website/versioned_docs/version-0.77.0/auth_auth_module.md deleted file mode 100644 index 5fc70df0..00000000 --- a/website/versioned_docs/version-0.77.0/auth_auth_module.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Multi-factor Authentication Modules -id: version-0.77.0-auth_auth_module -original_id: auth_auth_module ---- - -Multi-factor Authentication Modules are used in conjunction with [Authentication Provider](auth_auth_provider.html) to provide a fully configurable authentication framework. Each MFA module may provide one multi-factor authentication function. User can enable multiple mfa modules, but can only select one module in login process. - -## Defining an mfa auth module - -> We currently only support built-in mfa auth modules. Support for custom auth modules might arrive in the future. - -Multi-facor Auth modules are defined in `homeassistant/auth/mfa_modules/.py`. The auth module will need to provide an implementation of the `MultiFactorAuthModule` class. - -For an example of a fully implemented auth module, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/mfa_modules/insecure_example.py). - -Multi-factor Auth modules shall extend the following methods of `MultiFactorAuthModule` class. - -| method | Required | Description -| ------ | -------- | ----------- -| `@property def input_schema(self)` | Yes | Return a schema defined the user input form. -| `async def async_setup_flow(self, user_id)` | Yes | Return a SetupFlow to handle the setup workflow. -| `async def async_setup_user(self, user_id, setup_data)` | Yes | Set up user for use this auth module. -| `async def async_depose_user(self, user_id)` | Yes | Remove user information from this auth module. -| `async def async_is_user_setup(self, user_id)` | Yes | Return whether user is set up. -| `async def async_validation(self, user_id, user_input)` | Yes | Given a user_id and user input, return valiidation result. - -## Setup Flow - -Before user can use a multi-factor auth module, it has to be enabled or set up. All availaable modules will be listed in user profile page, user can enable the module he/she wants to use. A setup data entry flow will guide user finish the necessary steps. - -Each MFA module need to implement a setup flow handler extends from `mfa_modules.SetupFlow` (if only one simple setup step need, `SetupFlow` can be used as well). For example for Google Authenticator (TOTP, Time-based One Time Password) module, the flow will need to be: -- Generate a secret and store it on instance of setup flow -- Return `async_show_form` with a QR code in the description (injected as base64 via `description_placeholders`) -- User scans code and enters a code to verify it scanned correctly and clock in synced -- TOTP module saved the secret along with user_id, module is enabled for user - -## Workflow - -> TODO: draw a diagram - -User == select auth provider ==> LoginFlow.init == input/validate username/password ==> LoginFlow.finish ==> if user enabled mfa ==> LoginFlow.select_mfa_module ==> LoginFlow.mfa == input/validate MFA code ==> LoginFlow.finish ==> Done - -## Configuration example - -```yaml -# configuration.xml -homeassistant: - auth_providers: - - type: homeassistant - - type: legacy_api_password - auth_mfa_modules: - - type: totp - - type: insecure_example - users: [{'user_id': 'a_32_bytes_length_user_id', 'pin': '123456'}] -auth: -``` - -In this example, user will first select from `homeassistant` or `legacy_api_password` auth provider. For `homeassistant` auth provider, user will first input username/password, if that user enabled both `totp` and `insecure_example`, then user need select one auth module, then input Google Authenticator code or input pin code base on the selection. - -> insecure_example is only for demo purpose, please do not use it in production. - -## Validation session - -Not like auth provider, auth module use session to manage the validation. After auth provider validated, mfa module will create a validation session, include an experiation time and user_id from auth provider validate result. Mutli-factor auth moudle will not only verify the user input, and also verify the session is not experied. The validatoin session data storges in login flow instance. diff --git a/website/versioned_docs/version-0.77.0/auth_auth_provider.md b/website/versioned_docs/version-0.77.0/auth_auth_provider.md deleted file mode 100644 index f8249191..00000000 --- a/website/versioned_docs/version-0.77.0/auth_auth_provider.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Authentication Providers -id: version-0.77.0-auth_auth_provider -original_id: auth_auth_provider ---- - -Authentication providers confirm the identity of users. The user proofs their identity by going through the login flow for an auth provider. The auth provider defines the login flow and can ask the user all information this needs. This will commonly be username and password but could also include a 2FA token or other challenges. - -Once an authentication provider has confirmed the identity of a user, it will pass that on to Home Assistant in the form of a Credentials object. - -## Defining an auth provider - -> We currently only support built-in auth providers. Support for custom auth providers might arrive in the future. - -Auth providers are defined in `homeassistant/auth/providers/.py`. The auth provider module will need to provide an implementation of the `AuthProvider` class and `LoginFlow` class, it is what asks user for information and validates it base on `data_entry_flow`. - -For an example of a fully implemented auth provider, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/providers/insecure_example.py). - -Auth providers shall extend the following methods of `AuthProvider` class. - -| method | Required | Description -| ------ | -------- | ----------- -| async def async_login_flow(self) | Yes | Return an instance of the login flow for a user to identify itself. -| async def async_get_or_create_credentials(self, flow_result) | Yes | Given the result of a login flow, return a credentials object. This can either be an existing one or a new one. -| async def async_user_meta_for_credentials(credentials) | No | Callback called Home Assistant is going to create a user from a Credentials object. Can be used to populate extra fields for the user. - -Auth providers shall extend the following methods of `LoginFlow` class. - -| method | Required | Description -| ------ | -------- | ----------- -| async def async_step_init(self, user_input=None) | Yes | Handle the login form, see more detail in below. - -## async_step_init of LoginFlow - -> We may change this inteface in near future. - -`LoginFlow` extends `data_entry_flow.FlowHandler`. The first step of data entry flow is hard coded as `init`, so each flow has to implement `async_step_init` method. The pattern of `async_step_init` likes following pseudo-code: - -```python -async def async_step_init(self, user_input=None): - return self.async_show_form(step_id='init', data_schema='some schema to construct ui form') if user_input is None - return self.async_show_form(step_id='init', errors) if user_input is invalid - return await self.async_finish(username) if user_input is valid -``` diff --git a/website/versioned_docs/version-0.77.0/auth_index.md b/website/versioned_docs/version-0.77.0/auth_index.md deleted file mode 100644 index 27a6e311..00000000 --- a/website/versioned_docs/version-0.77.0/auth_index.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Authentication -sidebar_label: Introduction -id: version-0.77.0-auth_index -original_id: auth_index ---- - -Home Assistant has a built-in authentication system allowing different users to interact with Home Assistant. The authentication system consist of various parts. - -![Overview of how the different parts interact](/img/en/auth/architecture.png) - -## Authentication providers - -An authentication provider is used for users to authenticate themselves. It's up to the authentication provider to choose the method of authentication and the backend to use. By default we enable the built-in Home Assistant authentication provider which stores the users securely inside your configuration directory. - -The authentication providers that Home Assistant will use are specified inside `configuration.yaml`. It is possible to have multiple instances of the same authentication provider active. In that case, each will be identified by a unique identifier. Authentication providers of the same type will not share credentials. - -## Credentials - -Credentials store the authentication of a user with a specific authentication provider. It is produced when a user successfully authenticates. It will allow the system to find the user in our system. If the user does not exist, a new user will be created. This user will not be activated but will require approval by the owner. - -It is possible for a user to have multiple credentials linked to it. However, it can only have a single credential per specific authentication provider. - -## Users - -Each person is a user in the system. To log in as a specific user, authenticate with any of the authentication providers that are linked to this user. When a user logs in, it will get a refresh and an access token to make requests to Home Assistant. - -### Owner - -The first user to log in to Home Assistant will be marked as the owner. This user is able to manage users. - -## Clients - -Clients are applications that users use to access the Home Assistant API. Each client has a client identifier, a redirect uri and an optional client secret. The redirect uri is used to redirect the user after it has successfully authorized. - -## Access and refresh tokens - -The client will be provided with an authorization code when a user successfully authorizes with Home Assistant. This code can be used to retrieve an access and a refresh token. The access token will have a limited lifetime while refresh tokens will remain valid until a user deletes it. - -The access token is used to access the Home Assistant APIs. The refresh token is used to retrieve a new valid access token. diff --git a/website/versioned_docs/version-0.77.0/config_entries_config_flow_handler.md b/website/versioned_docs/version-0.77.0/config_entries_config_flow_handler.md deleted file mode 100644 index 52cdec05..00000000 --- a/website/versioned_docs/version-0.77.0/config_entries_config_flow_handler.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Config Flow Handlers -id: version-0.77.0-config_entries_config_flow_handler -original_id: config_entries_config_flow_handler ---- - -Config Entries uses the [Data Flow Entry framework](data_entry_flow_index.md) to allow users to create entries. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like hassio). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -To register your config flow handler with Home Assistant, register it with the config entries `HANDLERS` registry: - -```python -from homeassistant import config_entries, data_entry_flow - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): -``` - -> Temporarily, all config flow handlers will also need to add their component name to the `FLOWS` constant in `homeassistant/config_entries.py`. We are working on automating discovery. - -## Initializing a config flow from an external source - -You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing the config entry: - -```python -await hass.config_entries.flow.async_init( - 'hue', data=discovery_info, - context={'source': config_entries.SOURCE_DISCOVERY}) -``` - -The config flow handler will need to add a step to support the given source. The step should follow the same return values as a normal step. - -```python -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` - -If the result of the step is to show a form, the user will be able to continue the flow from the config panel. - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` diff --git a/website/versioned_docs/version-0.77.0/data_entry_flow_index.md b/website/versioned_docs/version-0.77.0/data_entry_flow_index.md deleted file mode 100644 index 7149848e..00000000 --- a/website/versioned_docs/version-0.77.0/data_entry_flow_index.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -title: Data Entry Flow -sidebar_label: Introduction -id: version-0.77.0-data_entry_flow_index -original_id: data_entry_flow_index ---- - -Data Entry Flow is a data entry framework that is part of Home Assistant. Data entry is done via data entry flows. A flow can represent a simple login form or a multi-step setup wizard for a component. A Flow Manager is managing all flows that are in progress and handles creation of new flows. - -Data Entry Flow is being used in Home Assistant to create config entries. - -## Flow Manager - -This is the class that manages the flows that are in progress. When instantiating one, you pass in two async callbacks: - -```python -async def async_create_flow(handler, context=context, data=data) -``` - -The manager delegates instantiating of config flow handlers to this async callback. This allows the parent of the manager to define their own way of finding handlers and preparing a handler for instantiation. For example, in the case of the config entry manager, it will make sure that the dependencies and requirements are setup. - -```python -async def async_finish_flow(flow, result) -``` - -This async callback is called when a flow is finished or aborted. i.e. `result['type'] in [RESULT_TYPE_CREATE_ENTRY, RESULT_TYPE_ABORT]`. The callback function can modify result and return it back, if the result type changed to `RESULT_TYPE_FORM`, the flow will continue running, display another form. - -If the result type is `RESULT_TYPE_FORM`, the result should like: -```python -{ - # The result type of the flow - 'type': RESULT_TYPE_FORM, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # name of the step, flow.async_step_[step_id] will be called when form submitted - 'step_id': 'init', - # a voluptuous schema to build and validate user input - 'data_schema': vol.Schema(), - # an errors dict, None if no errors - 'errors': errors, - # a detail information about the step - 'description_placeholders': description_placeholders, -} -``` - -If the result type is `RESULT_TYPE_CREATE_ENTRY`, the result should like: -```python -{ - # Data schema version of the entry - 'version': 2, - # The result type of the flow - 'type': RESULT_TYPE_CREATE_ENTRY, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # title and data as created by the handler - 'title': 'Some title', - 'result': { - 'some': 'data' - }, -} -``` - -If the result type is `RESULT_TYPE_ABORT`, the result should like: -```python -{ - # The result type of the flow - 'type': RESULT_TYPE_ABORT, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # the abort reason - 'reason': 'already_configured', -} -``` - - -## Flow Handler - -Flow handlers will handle a single flow. A flow contains one or more steps. When a flow is instantiated, the `FlowHandler.init_step` step will be called. Each step has three different possible results: "Show Form", "Abort" and "Create Entry". - -At a minimum, each flow handler will have to define a version number and a step. This doens't have to be `init`, as `async_create_flow` can assign `init_step` depends on diffreent workflow, for example in configuration, `context.source` will be use as `init_step`. - -The bare minimum config flow: - -```python -from homeassistant import data_entry_flow - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - # The schema version of the entries that it creates - # Home Assistant will call your migrate method if the version changes - # (this is not implemented yet) - VERSION = 1 - - async def async_step_user(self, user_input=None): - # Do something -``` - -### Show Form - -This result type will show a form to the user to fill in. You define the current step, the schema of the data (using voluptuous) and optionally a dictionary of errors. Title and description of the step will be provided via the translation file. Where this is defined depends on the context of the data entry flow. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema) - ) -``` - -After the user has filled in the form, the step method will be called again and the user input is passed in. Your step will only be called if the user input passes your data schema. When the user passes in data, you will have to do extra validation of the data. For example, you can verify that the passed in username and password are valid. - -If something is wrong, you can return a dictionary with errors. Each key in the error dictionary refers to a field name that contains the error. Use the key `base` if you want to show an error unrelated to a specific field. The specified errors need to refer to a key in a translation file. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # See next section on create entry usage - return self.create_entry(...) - - errors['base'] = 'auth_error' - - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema), - errors=errors - ) -``` - -#### Multi-step flows - -If the user input passes validation, you can again return one of the three return values. If you want to navigate the user to the next step, return the return value of that step: - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_init(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # Store info to use in next step - self.init_info = user_input - # Return the form of the next step - return await self.async_step_account() - - ... -``` - -### Create Entry - -When the result is "Create Entry", an entry will be created and passed to the parent of the flow manager. A success message is shown to the user and the flow is finished. You create an entry by passing a title and data. The title can be used in the UI to indicate to the user which entry it is. Data can be any data type, as long as it is JSON serializable. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - return self.create_entry( - title='Title of the entry', - data={ - 'something_special': user_input['username'] - } - ) -``` - -### Abort - -When a flow cannot be finished, you need to abort it. This will finish the flow and inform the user that the flow has finished. Reasons for a flow to not be able to finish can be that a device is already configured or not compatible with Home Assistant. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - return self.async_abort( - reason='not_supported' - ) -``` - -## Translations - -Data entry flows depend on translations for showing the text in the forms. It depends on the parent of a data entry flow manager where this is stored. - -## Initializing a config flow from an external source - -You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing a flow: - -```python -await flow_mgr.async_init('hue', context={'source': data_entry_flow.SOURCE_DISCOVERY}, data=discovery_info) -``` - -The config flow handler will not start with the `init` step. Instead, it will be instantiated with a step name equal to the source. The step should follow the same return values as a normal step. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` diff --git a/website/versioned_docs/version-0.77.0/external_api_rest_python.md b/website/versioned_docs/version-0.77.0/external_api_rest_python.md deleted file mode 100644 index c7b1c6ab..00000000 --- a/website/versioned_docs/version-0.77.0/external_api_rest_python.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: REST API - Python bindings -sidebar_label: REST API - Python bindings -id: version-0.77.0-external_api_rest_python -original_id: external_api_rest_python ---- - -This API is deprecated and was removed since Home Assistant 0.77.0 - -More information can be found in this [blog post](../../../blog/2018/08/13/deprecating-remote-package.html). diff --git a/website/versioned_docs/version-0.77.0/frontend_data.md b/website/versioned_docs/version-0.77.0/frontend_data.md deleted file mode 100644 index 6ea2adf2..00000000 --- a/website/versioned_docs/version-0.77.0/frontend_data.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: Frontend data -sidebar_label: Data -id: version-0.77.0-frontend_data -original_id: frontend_data ---- - -The frontend passes a single `hass` object around. This object contains the latest state and allows you to send commands back to the server. - -Whenever a state changes, a new version of the objects that changed are created. So you can easily see if something has changed by doing a strict equality check: - -```js -const changed = newVal !== oldVal; -``` - -## Data - -### `hass.states` - -An object containing the states of all entities in Home Assistant. The key is the entity_id, the value is the state object. - -```json -{ - "sun.sun": { - "entity_id": "sun.sun", - "state": "above_horizon", - "attributes": { - "next_dawn": "2018-08-18T05:39:19+00:00", - "next_dusk": "2018-08-17T18:28:52+00:00", - "next_midnight": "2018-08-18T00:03:51+00:00", - "next_noon": "2018-08-18T12:03:58+00:00", - "next_rising": "2018-08-18T06:00:33+00:00", - "next_setting": "2018-08-17T18:07:37+00:00", - "elevation": 60.74, - "azimuth": 297.69, - "friendly_name": "Sun" - }, - "last_changed": "2018-08-17T13:46:59.083836+00:00", - "last_updated": "2018-08-17T13:49:30.378101+00:00", - "context": { - "id": "74c2b3b429c844f18e59669e4b41ec6f", - "user_id": null - }, - }, - "light.ceiling_lights": { - "entity_id": "light.ceiling_lights", - "state": "on", - "attributes": { - "min_mireds": 153, - "max_mireds": 500, - "brightness": 180, - "color_temp": 380, - "hs_color": [ - 56, - 86 - ], - "rgb_color": [ - 255, - 240, - 35 - ], - "xy_color": [ - 0.459, - 0.496 - ], - "white_value": 200, - "friendly_name": "Ceiling Lights", - "supported_features": 151 - }, - "last_changed": "2018-08-17T13:46:59.129248+00:00", - "last_updated": "2018-08-17T13:46:59.129248+00:00", - "context": { - "id": "2c6bbbbb66a84a9dae097b6ed6c93383", - "user_id": null - }, - } -} -``` - -### `hass.user` - -The logged in user. - -```json -{ - "id": "758186e6a1854ee2896efbd593cb542c", - "name": "Paulus", - "is_owner": true, - "credentials": [ - { - "auth_provider_type": "homeassistant", - "auth_provider_id": null - } - ] -} -``` - -## Methods - -All methods starting with `call` are async methods. This means that they will return a `Promise` that will resolve with the result of the call. - -### `hass.callService(domain, service, data)` - -Call a service on the backend. - -```js -hass.callService('light', 'turn_on', { - entity_id: 'light.kitchen' -}); -``` - -### `hass.callWS(message)` - -Call a WebSocket command on the backend. - -```js -this.hass.callWS({ - type: 'config/auth/create', - name: 'Paulus', -}).then(userResponse => - console.log("Created user", userResponse.user.id)); -``` - -### `hass.callApi(method, path, data)` - -Call an API on the Home Assistant server. For example, if you want to fetch all Hass.io snapshots by issuing a GET request to `/api/hassio/snapshots`: - -```js -hass.callApi('get', 'hassio/snapshots') - .then(snapshots => console.log('Received snapshots!', snapshots)); -``` - -If you need to pass in data, pass a third argument: - -```js -hass.callApi('delete', 'notify.html5', { subscription: 'abcdefgh' }); -``` - -_We're moving away from API calls and are migrating everything to `hass.callWS(message)` calls._ diff --git a/website/versioned_docs/version-0.78.0/asyncio_working_with_async.md b/website/versioned_docs/version-0.78.0/asyncio_working_with_async.md deleted file mode 100644 index 239e4cd4..00000000 --- a/website/versioned_docs/version-0.78.0/asyncio_working_with_async.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: Working with Async -id: version-0.78.0-asyncio_working_with_async -original_id: asyncio_working_with_async ---- - -Although we have a backwards compatible API, using the async core directly will be a lot faster. Most core components have already been rewritten to leverage the async core. This includes the EntityComponent helper (foundation of light, switch, etc), scripts, groups and automation. - -## Interacting with the core - -[All methods in the Home Assistant core][dev-docs] are implemented in two flavors: an async version and a version to be called from other threads. The versions for other are merely wrappers that call the async version in a threadsafe manner. - -So if you are making calls to the core (the hass object) from within a callback or coroutine, use the methods that start with async_. If you need to call an async_ function that is a coroutine, your task must also be a coroutine. - -## Implementing an async component - -To make a component async, implement an async_setup. - -```python -def setup(hass, config): - # Setup your component outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup(hass, config): - # Setup your component inside of the event loop. -``` - -## Implementing an async platform - -For platforms we support async setup. Instead of setup_platform you need to have a coroutine async_setup_platform. - -```python -setup_platform(hass, config, add_entities, discovery_info=None): - # Setup your platform outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup_platform(hass, config, async_add_entities, - discovery_info=None): - # Setup your platform inside of the event loop -``` - -The only difference with the original parameters is that the `add_entities` function has been replaced by the async friendly callback `async_add_entities`. - -## Implementing an async entity - -You can make your entity async friendly by converting your update method to be async. This requires the dependency of your entities to also be async friendly! - -```python -class MyEntity(Entity): - def update(self): - """Retrieve latest state.""" - self._state = fetch_state() -``` - -Will turn into: - -```python -class MyEntity(Entity): - async def async_update(self): - """Retrieve latest state.""" - self._state = await async_fetch_state() -``` - -Make sure that all properties defined on your entity do not result in I/O being done. All data has to be fetched inside the update method and cached on the entity. This is because these properties are read from within the event loop and thus doing I/O will result in the core of Home Assistant waiting until your I/O is done. - -## Calling async functions from threads - -Sometimes it will happen that you’re in a thread and you want to call a function that is only available as async. Home Assistant includes a few async helper utilities to help with this. - -In the following example, `say_hello` will schedule `async_say_hello` and block till the function has run and get the result back. - -```python -from homeassistant.util.async_ import run_coroutine_threadsafe - -def say_hello(hass, target): - return run_coroutine_threadsafe( - hass.loop, async_say_hello, target).result() - -async def async_say_hello(hass, target): - return "Hello {}!".format(target) -``` - -## Calling sync functions from async - -If you are running inside an async context, it might sometimes be necessary to call a sync function. Do this like this: - -```python -# hub.update() is a sync function. -result = await hass.async_add_executor_job(hub.update) -``` - -## Starting independent task from async - -If you want to spawn a task that will not block the current async context, you can choose to create it as a task on the event loop. It will then be executed in parallel. - -```python -hass.async_create_task(async_say_hello(hass, target)) -``` - - -[dev-docs]: https://dev-docs.home-assistant.io/en/master/api/core.html -[dev-docs-async]: https://dev-docs.home-assistant.io/en/dev/api/util.html#module-homeassistant.util.async diff --git a/website/versioned_docs/version-0.78.0/auth_api.md b/website/versioned_docs/version-0.78.0/auth_api.md deleted file mode 100644 index 64e2900c..00000000 --- a/website/versioned_docs/version-0.78.0/auth_api.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -title: Authentication API -sidebar_label: API -id: version-0.78.0-auth_api -original_id: auth_api ---- - -This page will describe the steps required for your application to authorize against and integrate with Home Assistant instances. [See a demo](https://hass-auth-demo.glitch.me) powered by our helper lib [home-assistant-js-websocket](https://github.com/home-assistant/home-assistant-js-websocket). - -Each user has their own instance of Home Assistant which gives each user control over their own data. However, we also wanted to make it easy for third party developers to create applications that allow users to integrate with Home Assistant. To achieve this, we have adopted the [OAuth 2 specification][oauth2-spec] combined with the [OAuth 2 IndieAuth extension][indieauth-spec] for generating clients. - -## Clients - -Before you can ask the user to authorize their instance with your application, you will need a client. In traditional OAuth2, the server needs to generate a client before a user can authorize. However, as each server belongs to a user, we've adopted a slightly different approach from [IndieAuth][indieauth-clients]. - -The client ID you need to use is the website of your application. The redirect url has to be of the same host and port as the client ID. For example: - - - client id: `https://www.my-application.io` - - redirect uri: `https://www.my-application.io/hass/auth_callback` - -If you require a different redirect url (ie, if building a native app), you can add an HTML tag to the content of the website of your application (the client ID) with an approved redirect url. For example, add this to your site to whitelist redirect uri `hass://auth`: - -```html - -``` - -Home Assistant will scan the first 10kB of a website for link tags. - -## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) - -> All example URLs here are shown with extra spaces and new lines for display purposes only. - -The authorize url should contain `client_id` and `redirect_uri` as query parameters. - -``` -http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2F%3Fauth_callback%3D1 -``` - -Optionally you can also include a `state` parameter, this will be added to the redirect uri. The state is perfect to store the instance url that you are authenticating with. Example: - -``` -http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2Fauth_callback& - state=http%3A%2F%2Fhassio.local%3A8123 -``` - -The user will navigate to this link and be presented with instructions to log in and authorize your application. Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code and state as part of the query parameters. Example: - -``` -https://hass-auth-demo.glitch.me/auth_callback - code=12345& - state=http%3A%2F%2Fhassio.local%3A8123 -``` - -This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section). - -## Token - -The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. In thee case of refresh token, the token endpoint is also capable of revoking a token. - -All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`. - -### Authorization code - -> All requests to the token endpoint need to contain the exact same client ID as was used to redirect the user to the authorize endpoint. - -Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is: - -``` -grant_type=authorization_code& -code=12345& -client_id=https%3A%2F%2Fhass-auth-demo.glitch.me -``` - -The return response will be an access and refresh token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "refresh_token": "IJKLMNOPQRST", - "token_type": "Bearer" -} -``` - -The access token is a short lived token that can be used to access the API. The refresh token can be used to fetch new access tokens. The `expires_in` value is seconds that the access token is valid. - -An HTTP status code of 400 will be returned if an invalid request has been issued. The HTTP status code will be 403 if a token is requested for an inactive user. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Refresh token - -Once you have retrieved a refresh token via the grant type `authorization_code`, you can use it to fetch new access tokens. The request body is: - -``` -grant_type=refresh_token& -refresh_token=IJKLMNOPQRST& -client_id=https%3A%2F%2Fhass-auth-demo.glitch.me -``` - -The return response will be an access token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "token_type": "Bearer" -} -``` - -An HTTP status code of 400 will be returned if an invalid request has been issued. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Revoking a refresh token - -> client_id is not need for revoke refresh token - -The token endpoint is also capable of revoking a refresh token. Revoking a refresh token will immediately revoke the refresh token and all access tokens that it has ever granted. To revoke a refresh token, make the following request: - -``` -token=IJKLMNOPQRST& -action=revoke -``` - -The request will always respond with an empty body and HTTP status 200, regardless if the request was successful. - -## Long-lived access token - -A long-lived access token is usually used for 3rd party API calls and webhook-ish integrations. To generate a long-lived access token, an active websocket connection has to be established. - -Send websocket command `auth/long_lived_access_token` will create a long-lived access token for current user. Access token will not be saved in Home Assistant. User need to record the token in secure place. - -```json -{ - "id": 11, - "type": "auth/long_lived_access_token", - "client_name": "GPS Logger", - "client_icon": null, - "lifespan": 365 -} -``` - -Result will be a long-lived access token: - -```json -{ - "id": 11, - "type": "result", - "success": true, - "result": "ABCDEFGH" -} -``` - -## Making authenticated requests - -Once you have an access token, you can make authenticated requests to the Home Assistant APIs. - -For the websocket connection, pass the access token in the [authentication message](https://developers.home-assistant.io/docs/en/external_api_websocket.html#authentication-phase). - -For HTTP requests, pass the token type and access token as the authorization header: - -``` -Authorization: Bearer ABCDEFGH -``` - -### Example: cURL - -```shell -curl -X GET \ - https://your.awesome.home/api/error/all \ - -H 'Authorization: Bearer ABCDEFGH' -``` - -### Example: Python - -```python -import requests - -url = "https://your.awesome.home/api/error/all" -headers = { - 'Authorization': "Bearer ABCDEFGH", -} -response = requests.request('GET', url, headers=headers) - -print(response.text) -``` - -### Example: NodeJS -```JavaScript -fetch('https://your.awesome.home/api/error/all', { - headers: { Authorization: 'Bearer ABCDEFGH' } -}).then(function (response) { - if (!response.ok) { - return Promise.reject(response); - } - return response.text(); -}).then(function (body ) { - console.log(body); -}); -``` - -If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and so the user is no longer logged in. You should clear the user's data and ask the user to authorize again. - -[oauth2-spec]: https://tools.ietf.org/html/rfc6749 -[indieauth-spec]: https://indieauth.spec.indieweb.org/ -[indieauth-clients]: https://indieauth.spec.indieweb.org/#client-identifier diff --git a/website/versioned_docs/version-0.78.0/auth_auth_module.md b/website/versioned_docs/version-0.78.0/auth_auth_module.md deleted file mode 100644 index 68514f06..00000000 --- a/website/versioned_docs/version-0.78.0/auth_auth_module.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Multi-factor Authentication Modules -id: version-0.78.0-auth_auth_module -original_id: auth_auth_module ---- - -Multi-factor Authentication Modules are used in conjunction with [Authentication Provider](auth_auth_provider.html) to provide a fully configurable authentication framework. Each MFA module may provide one multi-factor authentication function. User can enable multiple mfa modules, but can only select one module in login process. - -## Defining an mfa auth module - -> We currently only support built-in mfa auth modules. Support for custom auth modules might arrive in the future. - -Multi-facor Auth modules are defined in `homeassistant/auth/mfa_modules/.py`. The auth module will need to provide an implementation of the `MultiFactorAuthModule` class. - -For an example of a fully implemented auth module, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/mfa_modules/insecure_example.py). - -Multi-factor Auth modules shall extend the following methods of `MultiFactorAuthModule` class. - -| method | Required | Description -| ------ | -------- | ----------- -| `@property def input_schema(self)` | Yes | Return a schema defined the user input form. -| `async def async_setup_flow(self, user_id)` | Yes | Return a SetupFlow to handle the setup workflow. -| `async def async_setup_user(self, user_id, setup_data)` | Yes | Set up user for use this auth module. -| `async def async_depose_user(self, user_id)` | Yes | Remove user information from this auth module. -| `async def async_is_user_setup(self, user_id)` | Yes | Return whether user is set up. -| `async def async_validate(self, user_id, user_input)` | Yes | Given a user_id and user input, return valiidation result. -| `async def async_initialize_login_mfa_step(self, user_id)` | No | Will be called once before display the mfa step of login flow. This is not initialization for the MFA module but the mfa step in login flow. - -## Setup Flow - -Before user can use a multi-factor auth module, it has to be enabled or set up. All availaable modules will be listed in user profile page, user can enable the module he/she wants to use. A setup data entry flow will guide user finish the necessary steps. - -Each MFA module need to implement a setup flow handler extends from `mfa_modules.SetupFlow` (if only one simple setup step need, `SetupFlow` can be used as well). For example for Google Authenticator (TOTP, Time-based One Time Password) module, the flow will need to be: -- Generate a secret and store it on instance of setup flow -- Return `async_show_form` with a QR code in the description (injected as base64 via `description_placeholders`) -- User scans code and enters a code to verify it scanned correctly and clock in synced -- TOTP module saved the secret along with user_id, module is enabled for user - -## Workflow - -> TODO: draw a diagram - -User == select auth provider ==> LoginFlow.init == input/validate username/password ==> LoginFlow.finish ==> if user enabled mfa ==> LoginFlow.select_mfa_module ==> initialize(optional) ==> LoginFlow.mfa == input/validate MFA code ==> LoginFlow.finish ==> Done - -## Configuration example - -```yaml -# configuration.xml -homeassistant: - auth_providers: - - type: homeassistant - - type: legacy_api_password - auth_mfa_modules: - - type: totp - - type: insecure_example - users: [{'user_id': 'a_32_bytes_length_user_id', 'pin': '123456'}] -``` - -In this example, user will first select from `homeassistant` or `legacy_api_password` auth provider. For `homeassistant` auth provider, user will first input username/password, if that user enabled both `totp` and `insecure_example`, then user need select one auth module, then input Google Authenticator code or input pin code base on the selection. - -> insecure_example is only for demo purpose, please do not use it in production. - -## Validation session - -Not like auth provider, auth module use session to manage the validation. After auth provider validated, mfa module will create a validation session, include an experiation time and user_id from auth provider validate result. Mutli-factor auth moudle will not only verify the user input, and also verify the session is not experied. The validatoin session data storges in login flow instance. diff --git a/website/versioned_docs/version-0.78.0/auth_index.md b/website/versioned_docs/version-0.78.0/auth_index.md deleted file mode 100644 index 3a02b171..00000000 --- a/website/versioned_docs/version-0.78.0/auth_index.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Authentication -sidebar_label: Introduction -id: version-0.78.0-auth_index -original_id: auth_index ---- - -Home Assistant has a built-in authentication system allowing different users to interact with Home Assistant. The authentication system consist of various parts. - -![Overview of how the different parts interact](/img/en/auth/architecture.png) - -## Authentication providers - -An authentication provider is used for users to authenticate themselves. It's up to the authentication provider to choose the method of authentication and the backend to use. By default we enable the built-in Home Assistant authentication provider which stores the users securely inside your configuration directory. - -The authentication providers that Home Assistant will use are specified inside `configuration.yaml`. It is possible to have multiple instances of the same authentication provider active. In that case, each will be identified by a unique identifier. Authentication providers of the same type will not share credentials. - -## Credentials - -Credentials store the authentication of a user with a specific authentication provider. It is produced when a user successfully authenticates. It will allow the system to find the user in our system. If the user does not exist, a new user will be created. This user will not be activated but will require approval by the owner. - -It is possible for a user to have multiple credentials linked to it. However, it can only have a single credential per specific authentication provider. - -## Users - -Each person is a user in the system. To log in as a specific user, authenticate with any of the authentication providers that are linked to this user. When a user logs in, it will get a refresh and an access token to make requests to Home Assistant. - -### Owner - -The first user to log in to Home Assistant will be marked as the owner. This user is able to manage users. - -## Clients - -Clients are applications that users use to access the Home Assistant API. Each client has a client identifier and a redirect uri. The redirect uri is used to redirect the user after it has successfully authorized. - -## Access and refresh tokens - -The client will be provided with an authorization code when a user successfully authorizes with Home Assistant. This code can be used to retrieve an access and a refresh token. The access token will have a limited lifetime while refresh tokens will remain valid until a user deletes it. - -The access token is used to access the Home Assistant APIs. The refresh token is used to retrieve a new valid access token. - -### Refresh token types - -Refresh token has 3 different types: -- *Normal*: is generated by a success log in request, and will be sent to user and possessed by user. -- *System*: can only be generated by system user. -- *Long-lived Access Token*: such refresh token is generated by user, but will not delivery to user, however the access token generated by this refresh token will send to user. diff --git a/website/versioned_docs/version-0.78.0/creating_component_code_review.md b/website/versioned_docs/version-0.78.0/creating_component_code_review.md deleted file mode 100644 index e680d3ba..00000000 --- a/website/versioned_docs/version-0.78.0/creating_component_code_review.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Checklist for creating a component -id: version-0.78.0-creating_component_code_review -original_id: creating_component_code_review ---- - -A checklist of things to do when you're adding a new component. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 1. Requirements - - 1. Requirement version pinned: `REQUIREMENTS = ['phue==0.8.1']` - 2. We no longer want requirements hosted on GitHub. Please upload to PyPi. - 3. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Configuration - - 1. Voluptuous schema present for config validation - 2. Default parameters specified in voluptuous schema, not in `setup(…)` - 3. Schema using as many generic config keys as possible from `homeassistant.const` - 4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`. - 5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation` - 6. Never depend on users adding things to `customize` to configure behavior inside your component. - -### 3. Component/platform communication - - 1. If you need to share global data with platforms, use the dictionary `hass.data`. `hass.data[DATA_XY]` while `XY` is the component is preferred over `hass.data[DOMAIN]`. - 2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`. - - -### 4. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - -```python -# bad -status = requests.get(url('/status')) - -# good -from phue import Bridge -bridge = Bridge(…) -status = bridge.status() -``` diff --git a/website/versioned_docs/version-0.78.0/development_guidelines.md b/website/versioned_docs/version-0.78.0/development_guidelines.md deleted file mode 100644 index 3a65729b..00000000 --- a/website/versioned_docs/version-0.78.0/development_guidelines.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Style guidelines -id: version-0.78.0-development_guidelines -original_id: development_guidelines ---- - -Home Assistant enforces strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. We automatically test every pull request as part of the linting process with [Coveralls](https://coveralls.io/github/home-assistant/home-assistant) and [Travis CI](https://travis-ci.org/home-assistant/home-assistant). - -Summary of the most relevant points: - -- Line length is limited to 79 characters (see below). -- Use 4 spaces per indentation level. We don't use tabs. -- Comments should be full sentences and end with a period. -- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered. -- Constants and the content of lists and dictionaries should be in alphabetical order. -- Avoid trailing whitespace but surround binary operators with a single space. -- Line separator should be set to `LF`. - -The maximum line length comes directly from the [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/#maximum-line-length), and is also used by the Python standard library. All code must pass these linting checks, and no exceptions will be made. There have already been numerous requests to increase the maximum line length, but after evaluating the options, the Home Assistant maintainers have decided to stay at 79 characters. This decision is final. - -Those points may require that you adjust your IDE or editor settings. - -## Our recommendations - -For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code unified. - -### Quotes - -Use single quotes `'` for single word and `"` for multiple words or sentences. - -```python -ATTR_WATERLEVEL = 'level' -CONF_ATTRIBUTION = "Data provided by the WUnderground weather service" -SENSOR_TYPES = { - 'alerts': ['Alerts', None], -} -``` - -### File headers - -The docstring in the file header should contain a link to the documentation to make it easy to find further information, especially about the configuration or details which are not mentioned in the code. - -```python -""" -Support for MQTT lights. - -For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/light.mqtt/ -""" -``` - -### Requirements - -Please place [Platform requirements](creating_platform_code_review.md#1-requirements) right after the imports. - -```python -[...] -from homeassistant.helpers.entity import Entity - -REQUIREMENTS = ['xmltodict==0.11.0'] -``` - -### Log messages - -There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. Try to avoid brackets and additional quotes around the output to make it easier for users to parse the log. A widely style is shown below but you are free to compose the messages as you like. - -```python -_LOGGER.error("No route to device: %s", self._resource) -``` - -```bash -2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18 -``` - -Don't print out wrong API keys, tokens, usernames, or passwords. -Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` in anything else. - -### Ordering of imports - -Instead of order the imports manually, use [`isort`](https://github.com/timothycrosley/isort). - -```bash -$ pip3 install isort -$ isort homeassistant/components/sensor/fixer.py -``` - -### Use new style string formatting - -Prefer [new style string formatting](https://www.python.org/dev/peps/pep-3101/) over old. - -```python -"{} {}".format('New', 'style') -"%s %s" % ('Old', 'style') -``` diff --git a/website/versioned_docs/version-0.78.0/device_registry_index.md b/website/versioned_docs/version-0.78.0/device_registry_index.md deleted file mode 100644 index 7b794c7e..00000000 --- a/website/versioned_docs/version-0.78.0/device_registry_index.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Device Registry -sidebar_label: Introduction -id: version-0.78.0-device_registry_index -original_id: device_registry_index ---- - -The device registry is a registry where Home Assistant keeps track of devices. A device is represented in Home Assistant via one or more entities. For example, a battery-powered temperature and a humidity sensor might expose entities for temperature, humidity and battery level. - -Device registry overview - -| Attribute | Description | -| --------- | ----------- | -| id | Unique ID of device (generated by Home Assistant) -| name | Name of this device -| connections | A set of tuples of `(connection_type, connection identifier)`. Connection types are defined in the device registry module. -| identifiers | Set of identifiers. They identify the device in the outside world. An example is a serial number. -| manufacturer | The manufacturer of the device. -| model | The model of the device. -| config_entries | Config entries that are linked to this device. -| sw_version | The firmware version of the device. -| via_hub | Identifier of a device that routes messages between this device and Home Assistant. Examples of such devices are hubs. This is used to show device topology in Home Assistant. - -## Defining devices - -> Entity device info is only read if the entity is loaded via a [config entry](config_entries_index.md). - -Each entity is able to define a device via the `device_info` property. This property is read when an entity is added to Home Assistant via a config entry. A device will be be matched up with an existing device via supplied identifiers and connections, like serial numbers or MAC addresses. - -```python -# Inside a platform -class HueLight(LightEntity): - - @property - def device_info(self): - return { - 'identifiers': { - # Serial numbers are unique identifiers within a specific domain - (hue.DOMAIN, self.unique_id) - }, - 'name': self.name, - 'manufacturer': self.light.manufacturername, - 'model': self.light.productname, - 'sw_version': self.light.swversion, - 'via_hub': (hue.DOMAIN, self.api.bridgeid), - } - -``` - -Components are also able to register devices in the case that there are no entities representing them. An example is a hub that communicates with the lights. - -```python -# Inside a component -from homeassistant.helpers import device_registry as dr - -device_registry = await dr.async_get_registry(hass) - -device_registry.async_get_or_create( - config_entry=entry.entry_id, - connections={ - (dr.CONNECTION_NETWORK_MAC, config.mac) - }, - identifiers={ - (DOMAIN, config.bridgeid) - }, - manufacturer='Signify', - name=config.name, - model=config.modelid, - sw_version=config.swversion, -) -``` diff --git a/website/versioned_docs/version-0.78.0/documentation_standards.md b/website/versioned_docs/version-0.78.0/documentation_standards.md deleted file mode 100644 index bf8eb5b0..00000000 --- a/website/versioned_docs/version-0.78.0/documentation_standards.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -title: Standards -id: version-0.78.0-documentation_standards -original_id: documentation_standards ---- - -To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation. - -## General Documentation - -* The language of the documentation should be American-English. -* Don't put two spaces after a period and avoid the "Oxford comma". -* There is no limit for the line length. You are allowed to write in a flowing text style. This will make it easier to use the GitHub online editor in the future. -* Be objective and not gender favoring, polarizing, race related or religion inconsiderate. -* The case of brand names, services, protocols, components, and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select". -* All headings should use the `{% linkable_title %}` tag. -* Do not use ALL CAPITALS for emphasis - use italics instead - -## Component and Platform Pages - -* The **Configuration Variables** section must use the `{% configuration %}` tag. -* Configuration variables must document the requirement status (`false` or `true`) -* Configuration variables must document the default value, if any. -* Configuration variables must document the accepted value types (`string`, `boolean`, `integer`, `list`) - * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`). -* Use YAML sequence syntax in the sample code if it is supported. -* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated. - * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`. - * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note. -* Component and platform names should be a link to their respective documentation pages. - -Example configuration block - -```yaml -{% configuration %} -some_key: - description: This is a description of what this key is for. - required: false - type: string, list - default: Optional default value - leave out if there isn't one -{% endconfiguration %} -``` - -## Templates - -* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the `{% raw %}` tag. -* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`. -* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)): - * `friendly_name` - * Single-line templates: - * `value_template` - * `level_template` - * `icon_template` - * Children of `data_template` -* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks): - * Strings inside of templates: - * States - * Entity IDs - * `unit_of_measurement` -* No whitespace around pipe character (`|`) for Jinja2 filters. -* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}). -* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}). -* Do not quote values for: - * `device_class` - * `platform` - * `condition` - * `service` - -## Renaming Pages - -It can happen that a component or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old component/platform name, to the page in a [note](/developers/documentation/create_page/#html). - -```text ---- -... -redirect_from: /getting-started/android/ ---- -``` - -Adding a redirect also applies if you move content around in the [documentation](/docs/). - -## Single vs. Double Quotation Marks - -Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required). - -### Examples - -#### {% linkable_title Double Quotes Outside, Single Quotes Inside (Valid) %} - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}" -``` - -#### Single Quotes Outside, Double Quotes Inside (Invalid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}' -``` - -#### Multi-Line Template (Valid) - - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: >- - {% if trigger.to_state.name == 'Dale\'s Bedroom' %} - Someone's in your base, killing your noobs! - {% else %} - It's just another door. - {% endif %} -``` - diff --git a/website/versioned_docs/version-0.78.0/external_api_websocket.md b/website/versioned_docs/version-0.78.0/external_api_websocket.md deleted file mode 100644 index 84d36dee..00000000 --- a/website/versioned_docs/version-0.78.0/external_api_websocket.md +++ /dev/null @@ -1,416 +0,0 @@ ---- -title: WebSocket API -id: version-0.78.0-external_api_websocket -original_id: external_api_websocket ---- - -Home Assistant contains a WebSocket API. This API can be used to stream information from a Home Assistant instance to any client that implements WebSockets. Implementations in different languages: - -- [JavaScript](https://github.com/home-assistant/home-assistant-js-websocket) - powers the frontend -- [Python](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket-client.py) - CLI client using [`asyncws`](https://async-websockets.readthedocs.io/en/latest/) -- [JavaScript/HTML](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket.html) - WebSocket connection in your browser - -Connect your websocket implementation to `ws://localhost:8123/api/websocket`. You will need a valid access token. - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`websocket_api` component](https://www.home-assistant.io/components/websocket_api/) to your `configuration.yaml` file to use the WebSocket API. - -## Server states - -1. Client connects. -1. Authentication phase starts. - - Server sends `auth_required` message. - - Client sends `auth` message. - - If `auth` message correct: go to 3. - - Server sends `auth_invalid`. Go to 6. -1. Send `auth_ok` message -1. Authentication phase ends. -1. Command phase starts. - 1. Client can send commands. - 1. Server can send results of previous commands. -1. Client or server disconnects session. - -During the command phase, the client attaches a unique identifier to each message. The server will add this identifier to each message so that the client can link each message to its origin. - -## Message format - -Each API message is a JSON serialized object containing a `type` key. After the authentication phase messages also must contain an `id`, an integer that contains the number of interactions. - -Example of an auth message: - -```json -{ - "type": "auth", - "access_token": "ABCDEFGHIJKLMNOPQ" -} -``` - -```json -{ - "id": 5, - "type":"event", - "event":{ - "data":{}, - "event_type":"test_event", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -## Authentication phase - -When a client connects to the server, the server will test if the client is authenticated. Authentication will not be necessary if no api_password is set or if the user fulfills one of the other criteria for authentication (trusted network, password in url/header). - -If no authentication is needed, the authentication phase will complete and the server will send an `auth_ok` message. - -```json -{ - "type": "auth_ok" -} -``` - -If authentication is necessary, the server sends out `auth_required`. - -```json -{ - "type": "auth_required" -} -``` - -This means that the next message from the client should be an auth message. You can authorize with an access token. - -```json -{ - "type": "auth", - "access_token": "ABCDEFGH" -} -``` - -For now, we also support authentication with an API password (legacy auth). - -```json -{ - "type": "auth", - "api_password": "supersecret" -} -``` - -If the client supplies valid authentication, the authentication phase will complete by the server sending the `auth_ok` message: - -```json -{ - "type": "auth_ok" -} -``` - -If the data is incorrect, the server will reply with `auth_invalid` message and disconnect the session. - -```json -{ - "type": "auth_invalid", - "message": "Invalid password" -} -``` - -## Command phase - -During this phase the client can give commands to the server. The server will respond to each command with a `result` message indicating when the command is done and if it was successful. - -```json -{ - "id": 6. - "type": "result", - "success": true, - // Can contain extra result info - "result": null -} -``` - -## Subscribe to events - -The command `subscribe_events` will subscribe your client to the event bus. You can either listen to all events or to a specific event type. If you want to listen to multiple event types, you will have to send multiple `subscribe_events` commands. - -```json -{ - "id": 18, - "type": "subscribe_events", - // Optional - "event_type": "state_changed" -} -``` - -The server will respond with a result message to indicate that the subscription is active. - -```json -{ - "id": 18, - "type": "result", - "success": true, - "result": null -} -``` - -For each event that matches, the server will send a message of type `event`. The `id` in the message will point at the original `id` of the `listen_event` command. - -```json -{ - "id": 18, - "type":"event", - "event":{ - "data":{ - "entity_id":"light.bed_light", - "new_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:24.265390+00:00", - "state":"on", - "attributes":{ - "rgb_color":[ - 254, - 208, - 0 - ], - "color_temp":380, - "supported_features":147, - "xy_color":[ - 0.5, - 0.5 - ], - "brightness":180, - "white_value":200, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:24.265390+00:00" - }, - "old_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:10.466994+00:00", - "state":"off", - "attributes":{ - "supported_features":147, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:10.466994+00:00" - } - }, - "event_type":"state_changed", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -### Unsubscribing from events - -You can unsubscribe from previously created subscription events. Pass the id of the original subscription command as value to the subscription field. - -```json -{ - "id": 19, - "type": "unsubscribe_events", - "subscription": 18 -} -``` - -The server will respond with a result message to indicate that unsubscribing was successful. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": null -} -``` - -### Calling a service - -This will call a service in Home Assistant. Right now there is no return value. The client can listen to `state_changed` events if it is interested in changed entities as a result of a service call. - -```json -{ - "id": 24, - "type": "call_service", - "domain": "light", - "service": "turn_on", - // Optional - "service_data": { - "entity_id": "light.kitchen" - } -} -``` - -The server will indicate with a message indicating that the service is done executing. - -```json -{ - "id": 24, - "type": "result", - "success": true, - "result": null -} -``` - -### Fetching states - -This will get a dump of all the current states in Home Assistant. - -```json -{ - "id": 19, - "type": "get_states" -} -``` - -The server will respond with a result message containing the states. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -### Fetching config - -This will get a dump of the current config in Home Assistant. - -```json -{ - "id": 19, - "type": "get_config" -} -``` - -The server will respond with a result message containing the config. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -### Fetching services - -This will get a dump of the current services in Home Assistant. - -```json -{ - "id": 19, - "type": "get_services" -} -``` - -The server will respond with a result message containing the services. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -### Fetching panels - -This will get a dump of the current registered panels in Home Assistant. - -```json -{ - "id": 19, - "type": "get_panels" -} -``` - -The server will respond with a result message containing the current registered panels. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -### Fetching camera thumbnails - -_Introduced in Home Assistant 0.69._ - -Return a b64 encoded thumbnail of a camera entity. - -```json -{ - "id": 19, - "type": "camera_thumbnail" -} -``` - -The server will respond with a result message containing the thumbnail. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -### Fetching media player thumbnails - -_Introduced in Home Assistant 0.69._ - -Fetch a base64 encoded thumbnail picture for a media player. - -```json -{ - "id": 19, - "type": "media_player_thumbnail", - "entity_id": "media_player.living_room" -} -``` - -The server will respond with the image encoded via base64. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Error handling - -If an error occurs, the `success` key in the `result` message will be set to `false`. It will contain an `error` key containing an object with two keys: `code` and `message`. - -| Code | Description | -| ----- | ------------ | -| 1 | A non-increasing identifier has been supplied. -| 2 | Received message is not in expected format (voluptuous validation error). -| 3 | Requested item cannot be found - -```json -{ - "id": 12, - "type":"result", - "success": false, - "error": { - "code": 2, - "message": "Message incorrectly formatted: expected str for dictionary value @ data['event_type']. Got 100" - } -} -``` diff --git a/website/versioned_docs/version-0.78.0/frontend_add_more_info.md b/website/versioned_docs/version-0.78.0/frontend_add_more_info.md deleted file mode 100644 index dccd6dda..00000000 --- a/website/versioned_docs/version-0.78.0/frontend_add_more_info.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Adding more info dialogs -id: version-0.78.0-frontend_add_more_info -original_id: frontend_add_more_info ---- - -Whenever the user taps or clicks on one of the cards, a more info dialog will show. The header of this dialog will be the state card, followed by the history of this entity for the last 24 hours. Below this the more info component is rendered for that entity. The more info component can show more information or allow more ways of control. - -The more info dialog for a light allows the user to control the color and the brightness. - -The instructions to add a more info dialog are very similar to adding a new card type. This example will add a new more info component for the domain `camera`: - - 1. Add `'camera'` to the array `DOMAINS_WITH_MORE_INFO` in the file [/common/const.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/common/const.js). - 2. Create the files `more-info-camera.js` in the folder [/dialogs/more-info/controls](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/dialogs/more-info/controls). - 3. Add `import './more-info-camera.js';` to [/dialogs/more-info/controls/more-info-content.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/dialogs/more-info/controls/more-info-content.js) diff --git a/website/versioned_docs/version-0.78.0/frontend_external_auth.md b/website/versioned_docs/version-0.78.0/frontend_external_auth.md deleted file mode 100644 index 5c6f0e1a..00000000 --- a/website/versioned_docs/version-0.78.0/frontend_external_auth.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: External Authentication -id: version-0.78.0-frontend_external_auth -original_id: frontend_external_auth ---- - -By default, the frontend will take care of its own authentication tokens. If none found, it will redirect the user to the login page and it will take care that the token is up to date. - -If you want to embed the Home Assistant frontend in an external app, you will want to store the authentication inside the app but make it available to the frontend. To support this, Home Assistant exposes an external authentication API. - -To activate this API, load the frontend with `?external_auth=1` appended to the URL. If this is passed in, Home Assistant will expect either `window.externalApp` (for Android) or `window.webkit.messageHandlers` (for iOS) to be defined containing the methods described below. - -## Get Access Token - -_This API has been introduced in Home Assistant 0.78._ - -When the frontend loads, it will request an access token from the external authentication. It does so by calling one of the following methods with an options object. The options object defines the callback method to be called with the response. - -```js -window.externalApp.getExternalAuth({ - callback: 'externalAuthSetToken' -}); -// or -window.webkit.messageHandlers.getExternalAuth.postMessage({ - callback: 'externalAuthSetToken' -}); -``` - -The response should contain a boolean if it was successful and an object containing an access token and the number of seconds that it will remain valid. Pass the response to the function defined in the options object. - -```js -// To be called by external app -window.externalAuthSetToken(true, { - "access_token": "qwere", - "expires_in": 1800 -}); - -// If unable to get new access token -window.externalAuthSetToken(false); -``` - -The frontend will call this method when the page first loads and whenever it needs a valid token but the previous received token has expired. - -## Revoke Token - -_This API has been introduced in Home Assistant 0.78._ - -When the user presses the logout button on the profile page, the external app will have to [revoke the refresh token](auth_api.md#revoking-a-refresh-token), and log the user out. - -```js -window.externalApp.revokeExternalAuth({ - callback: 'externalAuthSetToken' -}); -// or -window.webkit.messageHandlers.revokeExternalAuth.postMessage({ - callback: 'externalAuthSetToken' -}); -``` - -When done, the external app has to call the function defined in the options object. - -```js -// To be called by external app -window.externalAuthRevokeToken(true); - -// If unable to logout -window.externalAuthRevokeToken(false); -``` diff --git a/website/versioned_docs/version-0.78.0/hassio_addon_communication.md b/website/versioned_docs/version-0.78.0/hassio_addon_communication.md deleted file mode 100644 index dac4f70c..00000000 --- a/website/versioned_docs/version-0.78.0/hassio_addon_communication.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Add-On Communication -id: version-0.78.0-hassio_addon_communication -original_id: hassio_addon_communication ---- - -There are different ways for communication between add-ons inside Hass.io. - -## Network - -We use an internal network that allows to communicate with every add-on, even to/from Home Assistant, by using its name or alias. Only the add-ons which run on the host network are a bit limited. These can talk with all internal add-ons by their name but all other add-on can't address these add-on by name - using an alias works for both! - -Name/alias are used for communication inside Hass.io. -The name is generated using the following format: `{REPO}_{SLUG}`, e.g., `local_xy` or `3283fh_myaddon`. In this example, `{SLUG}` is defined in an add-ons `config.json`. You can use this name also as DNS name but you need replace the `_` with `-` to have a valid hostname. If an add-on is installed locally, `{REPO}` will be `local`. If the add-on is installed from a Github repository, `{REPO}` is a hashed identifier generated from the GitHub repository's URL (ex: https://github.com/xy/my_hassio_addons). See [here](https://github.com/home-assistant/hassio/blob/587047f9d648b8491dc8eef17dc6777f81938bfd/hassio/addons/utils.py#L17) to understand how this identifier is generated. Note that this identifier is required in certain service calls that use the [Hass.io add-on API][hassio-addon-api]. You can view the repository identifiers for all currently installed add-ons via a GET request to the hassio API `addons` endpoint. - -Use `hassio` for communication with the internal API. - -## Home Assistant - -An add-on can talk to the [Home Assistant API][hass-api] using the internal proxy. That makes it very easy to communicate with the API without knowing the password, port or any other information of the Home Assistant instance. Use this URL: `http://hassio/homeassistant/api` and internal communication is redirected to the right place. The next stept is to add `homeassistant_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN` and use this as Home-Assistant password. - -There is also a proxy for the [Home Assistant Websocket API][hass-websocket]. It works like the API proxy above and requires `HASSIO_TOKEN` as password. Use this URL: `http://hassio/homeassistant/websocket`. - -It is also possible to talk direct to the Home Assistant instance which is named `homeassistant` over the internal network. But you need to know the configuration that is used by the running instance. - -We have severals services for Hass.io inside Home Assistant to run tasks. To send data over STDIN to an add-on use the `hassio.addon_stdin` service. - -## Hass.io API - -To enables calls to the [Hass.io API][hassio-api], add `hassio_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN`. Now you can use the API over the URL: `http://hassio/`. Use the `HASSIO_TOKEN` with header `X-HASSIO-KEY`. It could be that you need also change the Hass.io API role like `hassio_role: default`. - -Add-ons can call some API commands without need set `hassio_api: true`: -- `/homeassistant/info` -- `/supervisor/info` -- `/addons` -- `/addons/self/...` -- `/services*` - -[hass-api]: https://www.home-assistant.io/developers/rest_api/ -[hass-websocket]: https://www.home-assistant.io/developers/websocket_api/ -[hassio-api]: https://github.com/home-assistant/hassio/blob/master/API.md -[hassio-addon-api]: https://github.com/home-assistant/hassio/blob/dev/API.md#restful-for-api-addons diff --git a/website/versioned_docs/version-0.78.0/hassio_addon_config.md b/website/versioned_docs/version-0.78.0/hassio_addon_config.md deleted file mode 100644 index b5723bf3..00000000 --- a/website/versioned_docs/version-0.78.0/hassio_addon_config.md +++ /dev/null @@ -1,206 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.78.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use `jq` inside your shell script to parse this data. However, you might have to install `jq` as a separate package in your container (see `Dockerfile` below). - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -## Add-on Docker file - -All add-ons are based on Alpine Linux 3.6. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | no | List of supported arch: `armhf`, `aarch64`, `amd64`, `i386`. Default all. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. diff --git a/website/versioned_docs/version-0.78.0/hassio_addon_security.md b/website/versioned_docs/version-0.78.0/hassio_addon_security.md deleted file mode 100644 index 488ff211..00000000 --- a/website/versioned_docs/version-0.78.0/hassio_addon_security.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Add-on security -id: version-0.78.0-hassio_addon_security -original_id: hassio_addon_security ---- - -Hass.io rates every add-on based on the wanted rights. An add-on with a rating of 6 is very secure. If an add-on has a rating of 1, you shouldn't run this add-on unless you are 100% sure that you can trust the source. - -## API Role - -For access to Hass.io API you need define a role or you run in default mode. This is only required for Hass.io API not Home Assistant proxy. Any of the role have also the default API calls inheret for that are no settings are required. - -### Available Roles - -| Role | Description | -|------|-------------| -| default | Have access to all `info` calls | -| homeassistant | Can access to all Home Assistant API endpoints | -| manager | Is for Add-ons they run CLIs and need extended rights | -| admin | Have access to every API call. That is the only one they can disable/enable the Add-on protection mode | - -## Protection - -Default, all add-ons run in protection enabled mode. This mode prevents the add-on from getting any rights on the system. If an add-on requires more rights, you can disable this protection via the API add-on options for that add-on. But be carful, an add-on with disabled protection can destroy your system! - -## Making a secure add-on - -As a developer, follow the following best practices to make your add-on secure: - -- Don't run on host network -- Create an AppArmor profile -- Map folders read only if you don't need write access -- If you need any API access, make sure you that you not grant to highest permission if you don't need it diff --git a/website/versioned_docs/version-0.79.0/creating_component_code_review.md b/website/versioned_docs/version-0.79.0/creating_component_code_review.md deleted file mode 100644 index ede6c04e..00000000 --- a/website/versioned_docs/version-0.79.0/creating_component_code_review.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Checklist for creating a component -id: version-0.79.0-creating_component_code_review -original_id: creating_component_code_review ---- - -A checklist of things to do when you're adding a new component. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on components level - -### 1. Requirements - - 1. Requirement version pinned: `REQUIREMENTS = ['phue==0.8.1']` - 2. We no longer want requirements hosted on GitHub. Please upload to PyPi. - 3. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Configuration - - 1. Voluptuous schema present for [configuration validation](development_validation.md) - 2. Default parameters specified in voluptuous schema, not in `setup(…)` - 3. Schema using as many generic config keys as possible from `homeassistant.const` - 4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`. - 5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation` - 6. Never depend on users adding things to `customize` to configure behavior inside your component. - -### 3. Component/platform communication - - 1. If you need to share global data with platforms, use the dictionary `hass.data`. `hass.data[DATA_XY]` while `XY` is the component is preferred over `hass.data[DOMAIN]`. - 2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`. - - -### 4. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - -```python -# bad -status = requests.get(url('/status')) - -# good -from phue import Bridge -bridge = Bridge(...) -status = bridge.status() -``` diff --git a/website/versioned_docs/version-0.79.0/creating_platform_code_review.md b/website/versioned_docs/version-0.79.0/creating_platform_code_review.md deleted file mode 100644 index 04f799d6..00000000 --- a/website/versioned_docs/version-0.79.0/creating_platform_code_review.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: Checklist for creating a platform -id: version-0.79.0-creating_platform_code_review -original_id: creating_platform_code_review ---- - -A checklist of things to do when you're adding a new platform. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on platform level - * Use `CONF_MONITORED_CONDITIONS` instead of `CONF_MONITORED_VARIABLES` - -### 1. Requirements - - 1. Requirement version should be pinned: `REQUIREMENTS = ['phue==0.8.1']` - 2. We no longer want requirements hosted on GitHub. Please upload to PyPi. - 3. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Dependencies - - 1. If you depend on a component for the connection, add it to your dependencies: `DEPENDENCIES = ['nest']` - -### 3. Configuration - - 1. Voluptuous schema present for [configuration validation](development_validation.md) - 2. Voluptuous schema extends schema from component
(e.g., `light.hue.PLATFORM_SCHEMA` extends `light.PLATFORM_SCHEMA`) - 3. Default parameters specified in voluptuous schema, not in `setup_platform(...)` - 4. Your `PLATFORM_SCHEMA` should use as many generic config keys as possible from `homeassistant.const` - ```python - import voluptuous as vol - - from homeassistant.const import CONF_FILENAME, CONF_HOST - from homeassistant.components.light import PLATFORM_SCHEMA - import homeassistant.helpers.config_validation as cv - - CONF_ALLOW_UNREACHABLE = 'allow_unreachable' - DEFAULT_UNREACHABLE = False - - PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_ALLOW_UNREACHABLE, - default=DEFAULT_UNREACHABLE): cv.boolean, - vol.Optional(CONF_FILENAME): cv.string, - }) - ``` - 5. Never depend on users adding things to `customize` to configure behavior inside your platform. - -### 4. Setup Platform - - 1. Test if passed in info (user/pass/host etc.) works. - 2. Group your calls to `add_devices` if possible. - 3. If platform adds extra services, format should be `._`. - -### 5. Entity - - 1. Extend entity from component, e.g., `class HueLight(Light)`. - 2. Avoid passing in `hass` as a parameter to the entity. When the entity has been added to Home Assistant, `hass` will be set on the entity by the helper in entity_platform.py. This means you can access `hass` as `self.hass` inside the entity. - 3. Do not call `update()` in constructor, use `add_entities(devices, True)` instead. - 4. Do not do any I/O inside properties. Cache values inside `update()` instead. - 5. The state and/or attributes should not contain relative time since something happened. Instead it should store UTC timestamps. - -### 6. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - -```python -# bad -status = requests.get(url('/status')) - -# good -from phue import Bridge -bridge = Bridge(...) -status = bridge.status() -``` diff --git a/website/versioned_docs/version-0.79.0/development_environment.md b/website/versioned_docs/version-0.79.0/development_environment.md deleted file mode 100644 index 0e5658f2..00000000 --- a/website/versioned_docs/version-0.79.0/development_environment.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.79.0-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example Centos would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -If you are using Windows as a development platform, make sure that you have the correct Microsoft [Visual C++ build tools](http://landinghub.visualstudio.com/visual-cpp-build-tools) installed. The installation of the most requirements and validation using `tox` will fail if this is not done correctly. Check the [Windows Compilers](https://wiki.python.org/moin/WindowsCompilers) section on the [Python website](https://www.python.org/) for details. - -Due to Home Assistant is mainly designed and developed on Linux distributions it is not recommended to develop on Windows machines. However on Windows 10 machines you should decide to set up a [Linux subsystem](https://docs.microsoft.com/de-de/windows/wsl/install-win10). - -Setup Linux subsystem. - -```bash -$ sudo apt-get update -$ sudo apt-get upgrade -$ echo 'export DISPLAY=:0' >> ~/.bashrc && . ~/.bashrc -$ sudo apt-get install xubuntu-desktop -y -``` - -It is recommended using [PyCharm](https://www.jetbrains.com/pycharm/download/) as debugger. Download and start PyCharm. - -```bash -$ wget https://download.jetbrains.com/python/pycharm-community-20XX.X.tar.gz -$ tar -xzf pycharm-community-20XX.X -$ ./pycharm.sh -``` - -In order to display the PyCharm GUI on Windows you need to run a X-Server like [VcXserv](https://sourceforge.net/projects/vcxsrv/). - -Also, make sure to install or upgrade the `setuptools` Python package. It contains compatibility improvements and adds automatic use of compilers: - -```bash -$ pip install --upgrade setuptools -``` - -### Developing on OS X - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 -``` - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv . -$ source bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation. - -```bash -$ hass -``` - -## Logging - -By default logging in home-assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` diff --git a/website/versioned_docs/version-0.79.0/documentation_create_page.md b/website/versioned_docs/version-0.79.0/documentation_create_page.md deleted file mode 100644 index d9a89d49..00000000 --- a/website/versioned_docs/version-0.79.0/documentation_create_page.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -title: Create a new page -id: version-0.79.0-documentation_create_page -original_id: documentation_create_page ---- - -For a platform or component page, the fastest way is to make a copy of an existing page and edit it. The [Component overview](https://www.home-assistant.io/components/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages. - -Please honor the [Standards](documentation_standards.md) we have for the documentation. - -If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers. - -```text ---- -layout: page -title: "Awesome Sensor" -description: "home-assistant.io web presence" -date: 2015-06-17 08:00 -sidebar: true -comments: false -sharing: true -footer: true -ha_release: "0.38" -ha_category: Sensor -ha_iot_class: "Local Polling" -ha_qa_scale: silver ---- - -Content...Written in markdown. - -### {% linkable_title Linkable Header %} -... -``` - -Please keep in mind that if the `date:` entry is in the future then the page will not show up. - -Additional keys for the file header: - -- `logo`: Please check the separate section below. -- `ha_release`: The release when the intregration was included, e.g., "0.38". If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`. -- `ha_category`: This entry is used to group the integration on the [Components overview](https://www.home-assistant.io/components/). -- `ha_iot_class`: [IoT class(/blog/2016/02/12/classifying-the-internet-of-things) is the classifier for the device's behavior. -- `ha_qa_scale`: [Quality scale](https://www.home-assistant.io/docs/quality_scale/) is the representation of the integration's quality. - -There are [pre-definied variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation. - -A couple of points to remember: - -- Document the needed steps to retrieve API keys or access token for the third party service or device if needed. -- Add screenshot to support the user where it make sense. -- Add the type of the device(s) (incl. firmware) you have tested when you know that there are multiple out there. - -### Configuration - -Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file. - -The **Configuration Variables** section must use the `{% configuration %} ... {% endconfiguration %}` tag. - -```text -{% configuration %} -api_key: - description: The API key to access the service. - required: true - type: string -name: - description: Name to use in the frontend. - required: false - default: The default name to use in the frontend. - type: string -monitored_conditions: - description: Conditions to display in the frontend. - required: true - type: map - keys: - weather: - description: A human-readable text summary. - temperature: - description: The current temperature. -{% endconfiguration %} -``` - -Available keys: - -- **`description:`**: That the variable is about. -- **`required:`**: If the variable is required. - -```text -required: true #=> Required -required: false #=> Optional -required: inclusive #=> Inclusive -required: exclusive #=> Exclusive -required: any string here #=> Any string here -``` -- **`type:`**: The type of the variable. Allowed entries: `string`, `int`, `time`, `template` or `map` (for a list of entries). For multiple possibilities use `[string, int]`. If you use `map` then you need to define `keys:` (see the [`template` sensor](/components/sensor.template/) for an example). -- **`default:`**: The default value for the variable. - -### Embedding Code - -You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in back-ticks. - -When you're writing code that is to be executed on the terminal, prefix it with `$`. - -### Templates - -For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) is [Jinja](http://jinja.pocoo.org/) used. Check the [Documentation Standards](documentation_standards.md) for further details. - -If you are don't escape templates then they will be rendered and appear blank on the website. - -### HTML - -The direct usage of HTML is supported but not recommended. The note boxes are an exception. - -```html -

- You need to enable telnet on your router. -

-``` - -### Images, icons and logos - -The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent. - -| Type | Location | -| :----------- |:----------------------------------------------| -| logos | source/images/supported_brands | -| blog | source/images/blog | -| screenshots | source/images/components | - -Not everything (product, component, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/). - -### Linking From The Sidebar - -If you are adding a new page that requires linking from the sidebar you need to edit the `docs_navigation.html` file in `home-assistant.github.io/source/_includes/asides/docs_navigation.html`. diff --git a/website/versioned_docs/version-0.79.0/documentation_index.md b/website/versioned_docs/version-0.79.0/documentation_index.md deleted file mode 100644 index 1ffc718a..00000000 --- a/website/versioned_docs/version-0.79.0/documentation_index.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Documentation -id: version-0.79.0-documentation_index -original_id: documentation_index ---- - -The user documentation is located at [https://www.home-assistant.io](https://www.home-assistant.io). This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know about HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process for working on the website is no different from working on Home Assistant itself. You work on your change and propose it via a Pull Request (PR). - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.3.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` -- In your home-assistant.io root directory, run `$ bundle` to install the gems you need. - -Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` - -Then you can work on the documentation: - -- Fork home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.io). -- Create/edit/update a page in the directory `source/_components/` for your platform/component. The Home Assistant documention itself is located in the directory `source/_docs/`. -- Test your changes to home-assistant.io locally: run `rake preview` and navigate to [http://127.0.0.1:4000](http://127.0.0.1:4000) -- Create a Pull Request (PR) against the **next** branch of home-assistant.io if your documentation is a new feature, platform, or component. -- Create a Pull Request (PR) against the **current** branch of home-assistant.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -It could be necessary that you run `rake generate` prior to `rake preview` for the very first preview. - -Site generated by `rake` is only available locally. If you are developing on a headless machine use port forwarding: - -```bash -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` - diff --git a/website/versioned_docs/version-0.79.0/hassio_addon_communication.md b/website/versioned_docs/version-0.79.0/hassio_addon_communication.md deleted file mode 100644 index ca52ff40..00000000 --- a/website/versioned_docs/version-0.79.0/hassio_addon_communication.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Add-On Communication -id: version-0.79.0-hassio_addon_communication -original_id: hassio_addon_communication ---- - -There are different ways for communication between add-ons inside Hass.io. - -## Network - -We use an internal network that allows to communicate with every add-on, even to/from Home Assistant, by using its name or alias. Only the add-ons which run on the host network are a bit limited. These can talk with all internal add-ons by their name but all other add-on can't address these add-on by name - using an alias works for both! - -Name/alias are used for communication inside Hass.io. -The name is generated using the following format: `{REPO}_{SLUG}`, e.g., `local_xy` or `3283fh_myaddon`. In this example, `{SLUG}` is defined in an add-ons `config.json`. You can use this name also as DNS name but you need replace the `_` with `-` to have a valid hostname. If an add-on is installed locally, `{REPO}` will be `local`. If the add-on is installed from a Github repository, `{REPO}` is a hashed identifier generated from the GitHub repository's URL (ex: https://github.com/xy/my_hassio_addons). See [here](https://github.com/home-assistant/hassio/blob/587047f9d648b8491dc8eef17dc6777f81938bfd/hassio/addons/utils.py#L17) to understand how this identifier is generated. Note that this identifier is required in certain service calls that use the [Hass.io add-on API][hassio-addon-api]. You can view the repository identifiers for all currently installed add-ons via a GET request to the hassio API `addons` endpoint. - -Use `hassio` for communication with the internal API. - -## Home Assistant - -An add-on can talk to the [Home Assistant API][hass-api] using the internal proxy. That makes it very easy to communicate with the API without knowing the password, port or any other information of the Home Assistant instance. Use this URL: `http://hassio/homeassistant/api` and internal communication is redirected to the right place. The next stept is to add `homeassistant_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN` and use this as Home-Assistant password. - -There is also a proxy for the [Home Assistant Websocket API][hass-websocket]. It works like the API proxy above and requires `HASSIO_TOKEN` as password. Use this URL: `http://hassio/homeassistant/websocket`. - -It is also possible to talk direct to the Home Assistant instance which is named `homeassistant` over the internal network. But you need to know the configuration that is used by the running instance. - -We have severals services for Hass.io inside Home Assistant to run tasks. To send data over STDIN to an add-on use the `hassio.addon_stdin` service. - -## Hass.io API - -To enables calls to the [Hass.io API][hassio-api], add `hassio_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN`. Now you can use the API over the URL: `http://hassio/`. Use the `HASSIO_TOKEN` with header `X-HASSIO-KEY`. It could be that you need also change the Hass.io API role like `hassio_role: default`. - -Add-ons can call some API commands without need set `hassio_api: true`: -- `/homeassistant/api` -- `/homeassistant/websocket` -- `/homeassistant/stream` -- `/addons/self/...` -- `/services*` - -[hass-api]: https://www.home-assistant.io/developers/rest_api/ -[hass-websocket]: https://www.home-assistant.io/developers/websocket_api/ -[hassio-api]: https://github.com/home-assistant/hassio/blob/master/API.md -[hassio-addon-api]: https://github.com/home-assistant/hassio/blob/dev/API.md#restful-for-api-addons diff --git a/website/versioned_docs/version-0.79.0/hassio_hass.md b/website/versioned_docs/version-0.79.0/hassio_hass.md deleted file mode 100644 index deededd5..00000000 --- a/website/versioned_docs/version-0.79.0/hassio_hass.md +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: Hass.io <> Home Assistant integration development -sidebar_label: HASS Integration development -id: version-0.79.0-hassio_hass -original_id: hassio_hass ---- - -These steps will help you connect your local Home Assistant to a remote Hass.io instance. You can then make changes locally to either the Hass.io component or the frontend and test it out against a real instance. - -For this guide, we're going to assume that you have an Hass.io instance up and running. If you don't, you can use the generic installation method to install it inside a [virtual machine](https://github.com/home-assistant/hassio-build/tree/master/install#install-hassio). - -## API Access - -To develop for the frontend, we're going to need API access to the supervisor. - -- Add our developer Add-on repository: https://github.com/home-assistant/hassio-addons-development -- Install the Add-on "Remote API proxy" - - ## Having Home Assistant connect to remote Hass.io - - The connection with the supervisor is hidden inside the host and is only accessible from applications running on the host. So to make it accessible for our Home Assistant instance, we will need to route the connection to our computer running Home Assistant. We're going to do this by forwarding the API with "Remote API proxy" Add-on. - -First, make sure Home Assistant will load the Hass.io component by adding `hassio:` to your `configuration.yaml` file. Next, we will need to tell Hass.io component how to connect to the remote Hass.io instance, we do this by setting the `HASSIO` and `HASSIO_TOKEN` environment variables when starting Home Assistant. Note that the `HASSIO` value is not the same as the one that we saw above and the `HASSIO_TOKEN` is available inside log output of "Remote API Add-on" (This change every restart of this Add-on!). - -```bash -HASSIO=:80 HASSIO_TOKEN= hass -``` - -Voila. Your local Home Assistant installation will now connect to a remote Hass.io instance. - -## Frontend development - -> This requires Home Assistant 0.71 or later. - -We need a couple more steps to do frontend development. First, make sure you have a Home Assistant frontend development set up ([instructions](frontend_index.md)). - -Update the Hass.io component configuration in your `configuration.yaml` to point at the frontend repository: - -```yaml -# configuration.yaml -hassio: - development_repo: /home/paulus/dev/hass/home-assistant-polymer -``` - -To build a local version of the Hass.io panel, go to the frontend repository and run: - -```bash -cd hassio -script/build_hassio -``` - -Now start Home Assistant as discussed in the previous section and it will now connect to the remote Hass.io but show your local frontend. - -We're currently transitioning in how we're building the frontend so we don't have an incremental development mode just yet. For now, after making a local change, run `script/build_hassio` again. diff --git a/website/versioned_docs/version-0.79.0/integration_quality_scale_index.md b/website/versioned_docs/version-0.79.0/integration_quality_scale_index.md deleted file mode 100644 index eedba120..00000000 --- a/website/versioned_docs/version-0.79.0/integration_quality_scale_index.md +++ /dev/null @@ -1,51 +0,0 @@ ---- -title: Integration Quality Scale -sidebar_label: Introduction -id: version-0.79.0-integration_quality_scale_index -original_id: integration_quality_scale_index ---- - -The Integration Quality Scale scores each integration based on the code quality and user experience. Each level of the quality scale consists of a list of requirements. If an integration matches all requirements, it's considered to have reached that level. - -> Suggestions for changes can be done by creating an issue in the [architecture repo](https://github.com/home-assistant/architecture/issues/). - -# No score - -This integration passes the bare minimum requirements to become part of the index. - - - Satisfy all requirements for [creating components](creating_component_code_review.md) and [creating platforms](creating_platform_code_review.md). - - Configurable via `configuration.yaml` - -# Silver 🥈 - -This integration is able to cope when things go wrong. It will not print any exceptions nor will it fill the log with retry attempts. - -- Set an appropriate `SCAN_INTERVAL` (if a polling integration) -- Raise `PlatformNotReady` if unable to connect during platform setup (if appropriate) -- Handles expiration of auth credentials. Refresh if possible or print correct error and fail setup. If based on a config entry, should trigger a new config entry flow to re-authorize. -- Handles internet unavailable. Log a warning once when unavailable, log once when reconnected. -- Handles device/service unavailable. Log a warning once when unavailable, log once when reconnected. -- Set `available` property to `False` if appropriate ([docs](entity_index.md#generic-properties)) -- Entities have unique ID (if available) ([docs](entity_registry_index.md#unique-id-requirements)) - -# Gold 🥇 - -This is a solid integration that is able to survive poor conditions and can be configured via the user interface. - -- Configurable via config entries. - - Don't allow configuring already configured device/service (example: no 2 entries for same hub) - - Tests for the config flow - - Discoverable (if available) -- Entities have device info (if available) ([docs](device_registry_index.md#defining-devices)) -- States are translated in the frontend (text-based sensors only, [docs](internationalization_index.md)) -- Tests for reading data from/controlling the integration ([docs](development_testing.md)) -- Has a code owner - -# Platinum 🏆 - -Best of the best. The integration is completely async, meaning it's super fast. Integrations that reach platinum level will require approval by the code owner for each PR. - -- Set appropriate `PARALLEL_UPDATES` constant -- Support config entry unloading (called when config entry is removed) -- Integration + dependency are async -- Uses aiohttp and allows passing in websession (if making HTTP requests) diff --git a/website/versioned_docs/version-0.80.0/auth_index.md b/website/versioned_docs/version-0.80.0/auth_index.md deleted file mode 100644 index 766f7e04..00000000 --- a/website/versioned_docs/version-0.80.0/auth_index.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Authentication -sidebar_label: Introduction -id: version-0.80.0-auth_index -original_id: auth_index ---- - -Home Assistant has a built-in authentication system allowing different users to interact with Home Assistant. The authentication system consist of various parts. - -![Overview of how the different parts interact](/img/en/auth/architecture.png) - -## Authentication providers - -An authentication provider is used for users to authenticate themselves. It's up to the authentication provider to choose the method of authentication and the backend to use. By default we enable the built-in Home Assistant authentication provider which stores the users securely inside your configuration directory. - -The authentication providers that Home Assistant will use are specified inside `configuration.yaml`. It is possible to have multiple instances of the same authentication provider active. In that case, each will be identified by a unique identifier. Authentication providers of the same type will not share credentials. - -## Credentials - -Credentials store the authentication of a user with a specific authentication provider. It is produced when a user successfully authenticates. It will allow the system to find the user in our system. If the user does not exist, a new user will be created. This user will not be activated but will require approval by the owner. - -It is possible for a user to have multiple credentials linked to it. However, it can only have a single credential per specific authentication provider. - -## Users - -Each person is a user in the system. To log in as a specific user, authenticate with any of the authentication providers that are linked to this user. When a user logs in, it will get a refresh and an access token to make requests to Home Assistant. - -### Owner - -The user that is created during onboarding will be marked as "owner". The owner is able to manage other users and will always have access to all permissions. - -## Groups - -Users are a member of one or more groups. Group membership is how a user is granted permissions. - -## Permission Policy - -This is the permission policy that describes to which resources a group has access. For more information about permissions and policies, see [Permissions](auth_permissions.md). - -## Access and refresh tokens - -Applications that want to access Home Assistant will ask the user to start an authorization flow. The flow results in an authorization code when a user successfully authorizes the application with Home Assistant. This code can be used to retrieve an access and a refresh token. The access token will have a limited lifetime while refresh tokens will remain valid until a user deletes it. - -The access token is used to access the Home Assistant APIs. The refresh token is used to retrieve a new valid access token. - -### Refresh token types - -There are three different types of refresh tokens: - -- *Normal*: These are the tokens that are generated when a user authorizes an application. The application will hold on to these tokens on behalf of the user. -- *Long-lived Access Token*: These are refresh tokens that back a long lived access token. They are created internally and never exposed to the user. -- *System*: These tokens are limited to be generated and used by system users like Hass.io. They are never exposed to the user. diff --git a/website/versioned_docs/version-0.80.0/auth_permissions.md b/website/versioned_docs/version-0.80.0/auth_permissions.md deleted file mode 100644 index f1ea8a7f..00000000 --- a/website/versioned_docs/version-0.80.0/auth_permissions.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: Permissions -id: version-0.80.0-auth_permissions -original_id: auth_permissions ---- - -> This is an experimental feature that is not enabled or enforced yet - -Permissions limit the things a user has access to or can control. Permissions are attached to groups, of which a user can be a member. The combined permissions of all groups a user is a member of decides what a user can and cannot see or control. - -Permissions do not apply to the user that is flagged as "owner". This user will always have access to everything. - -## General permission structure - -Policies are dictionaries that at the root level consist of different categories of permissions. In the current implementation this is limited to just entities. - -```python -{ - "entities": … -} -``` - -Each category can further split into subcategories that describe parts of that category. - -```python -{ - "entities": { - "domains": …, - "entity_ids": … - } -} -``` - -If a category is ommitted, the user will not have permission to that category. - -When defining a policy, any dictionary value at any place can be replaced with `True` or `None`. `True` means that permission is granted and `None` means use default, which is deny access. - -## Entities - -Entity permissions can be set on a per entity and per domain basis using the subcategories `entity_ids` and `domains`. Granting access to an entity means a user will be able to read the state and control it. - -If an entity is specified in both the `entity_ids` and `domains` subcategory, the `entity_ids` result will be used, unless it is `None`. In the following example, the user will have access to all light entities except for `light.kitchen`. - -```python -{ - "entities": { - "domains": { - "light": True - }, - "entity_ids": { - "light.kitchen": False - } - } -} -``` - -## Merging policies - -If a user is a member of multiple groups, the groups permission policies will be combined into a single policy at runtime. When merging policies, we will look at each level of the dictionary and compare the values for each source using the following methodology: - -1. If any of the values is `True`, the merged value becomes `True`. -2. If any value is a dictionary, the merged value becomes a dictionary created by recursively checking each value using this methodology. -3. If all values are `None`, the merged value becomes `None`. - -Let's look at an example: - -```python -{ - "entities": { - "entity_ids": { - "light.kitchen": True - } - } -} -``` - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -Once merged becomes - -```python -{ - "entities": { - "entity_ids": True - } -} -``` diff --git a/website/versioned_docs/version-0.80.0/development_catching_up.md b/website/versioned_docs/version-0.80.0/development_catching_up.md deleted file mode 100644 index 08f37dac..00000000 --- a/website/versioned_docs/version-0.80.0/development_catching_up.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -title: Catching up with Reality -id: version-0.80.0-development_catching_up -original_id: development_catching_up ---- - -If it's taking a while to develop your feature, and you want to catch up with what's in the current Home Assistant `dev` branch, you can use `git rebase`. This will pull the latest Home Assistant changes locally, rewind your commits, bring in the latest changes from Home Assistant, and replay all of your commits on top. - -> If you use the workflow below, it is important that you force push the update as described. Git might prompt you to do `git pull` first. Do **NOT** do that! It would mess up your commit history. - -```bash -# Run this from your feature branch -$ git fetch upstream dev # to pull the latest changes into a local dev branch -$ git rebase upstream/dev # to put those changes into your feature branch before your changes -``` - -If rebase detects conflicts, repeat this process until all changes have been resolved: - -1. `git status` shows you the file with the conflict; edit the file and resolve the lines between `<<<< | >>>>` -3. Add the modified file: `git add ` or `git add .` -4. Continue rebase: `git rebase --continue` -5. Repeat until you've resolved all conflicts - -After rebasing your branch, you will have rewritten history relative to your GitHub fork's branch. When you go to push you will see an error that your history has diverged from the original branch. In order to get your GitHub fork up-to-date with your local branch, you will need to force push, using the following command: - -```bash -# Run this from your feature branch -$ git push origin --force -``` - -Other workflows are covered in detail in the [Github documentation](https://help.github.com/articles/fork-a-repo/). Add an additional `remote` after you clone your fork. - -```bash -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -Then, `git pull --rebase upstream dev`. - diff --git a/website/versioned_docs/version-0.80.0/development_environment.md b/website/versioned_docs/version-0.80.0/development_environment.md deleted file mode 100644 index 2e9cb0af..00000000 --- a/website/versioned_docs/version-0.80.0/development_environment.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.80.0-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example Centos would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Due to Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run -``` -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is setup, perform install as for Linux - -```bash -$ sudo apt-get update -$ sudo apt-get install python3-pip python3-dev python3-venv -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```bash -mkdir -p ../config -hass -c ../config -``` - -### Developing on OS X - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 autoconf -``` - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv . -$ source bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```bash -$ hass -``` - -## Logging - -By default logging in home-assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` diff --git a/website/versioned_docs/version-0.80.0/development_submitting.md b/website/versioned_docs/version-0.80.0/development_submitting.md deleted file mode 100644 index bfb9915c..00000000 --- a/website/versioned_docs/version-0.80.0/development_submitting.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Submit your work -id: version-0.80.0-development_submitting -original_id: development_submitting ---- - -> Always base your Pull Requests of of the current **`dev`** branch, not `master`. - -Submit your improvements, fixes, and new features to Home Assistant one at a time, using GitHub [Pull Requests](https://help.github.com/articles/using-pull-requests). Here are the steps: - - 1. From your fork's dev branch, create a new branch to hold your changes: - - `git checkout -b some-feature` - - 2. Make your changes, create a [new platform](creating_platform_index.md), develop a [new component](creating_component_index.md), or fix [issues](https://github.com/home-assistant/home-assistant/issues). - - 3. [Test your changes](development_testing.md) and check for style violations. - - 4. If everything looks good according to these [musts](development_checklist.md), commit your changes: - - `git add .` - - `git commit -m "Added some-feature"` - - * Write a meaningful commit message and not only `Update` or `Fix`. - * Use a capital letter to start with your commit message. - * Don't prefix your commit message with `[bla.bla]` or `platform:`. - * Consider adding tests to ensure that your code works. - - 5. Push your committed changes back to your fork on GitHub: - - `git push origin HEAD` - - 6. Follow [these steps](https://help.github.com/articles/creating-a-pull-request/) to create your pull request. - - * On GitHub, navigate to the main page of the Home Assistant repository. - * In the "Branch" menu, choose the branch that contains your commits (from your fork). - * To the right of the Branch menu, click **New pull request**. - * Use the base branch dropdown menu to select the branch you'd like to merge your changes into, then use the compare branch drop-down menu to choose the topic branch you made your changes in. Make sure the Home Assistant branch matches with your forked branch (`dev`) else you will propose ALL commits between branches. - * Type a title and complete the provided description for your pull request. - * Click **Create pull request**. - - 7. Check for comments and suggestions on your pull request and keep an eye on the [CI output](https://travis-ci.org/home-assistant/home-assistant/). - diff --git a/website/versioned_docs/version-0.80.0/development_testing.md b/website/versioned_docs/version-0.80.0/development_testing.md deleted file mode 100644 index f2537f1b..00000000 --- a/website/versioned_docs/version-0.80.0/development_testing.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Testing your code -id: version-0.80.0-development_testing -original_id: development_testing ---- - -As it states in the [Style guidelines section](development_guidelines.md) all code is checked to verify the following: - -- All the unit tests pass -- All code passes the checks from the linting tools - -Local testing is done using Tox, which has been installed as part of running `script/setup` in the [virtual environment](development_environment.md). To start the tests, activate the virtual environment and simply run the command: - -```bash -$ tox -``` -**Important:** Run `tox` before you create your pull request to avoid annoying fixes. - -Running Tox will run unit tests against the locally available Pythons, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one tox target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py36` runs unit tests only on Python 3.6. - -Tox uses virtual environments under the hood to create isolated testing environments. The tox virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell Tox to recreate the virtual environments. - -### Adding new dependencies to test environment - -If you are working on tests for a component or platform and you need the dependencies available inside the Tox environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments. - -### Running single tests using Tox - -You can pass arguments via Tox to py.test to be able to run single test suites or test files. Replace `py36` with the Python version that you use. - -```bash -# Stop after the first test fails -$ tox -e py36 -- tests/test_core.py -x -# Run test with specified name -$ tox -e py36 -- tests/test_core.py -k test_split_entity_id -# Fail a test after it runs for 2 seconds -$ tox -e py36 -- tests/test_core.py --timeout 2 -# Show the 10 slowest tests -$ tox -e py36 -- tests/test_core.py --duration=10 -``` - -### Testing outside of Tox - -Running tox will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without Tox, you'll need to install the test dependencies into your Python environment: - -```bash -$ pip3 install -r requirements_test_all.txt -``` - -Now that you have all test dependencies installed, you can run tests on individual files: - -```bash -$ flake8 homeassistant/core.py -$ pylint homeassistant/core.py -$ pydocstyle homeassistant/core.py -$ py.test tests/test_core.py -``` - -You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script: - -```bash -$ script/lint -``` - -### Preventing Linter Errors - -Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them! - -```bash -$ pip3 install flake8 flake8-docstrings -$ flake8 --install-hook=git -``` - -The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8. - -### Notes on PyLint and PEP8 validation - -If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member. diff --git a/website/versioned_docs/version-0.80.0/documentation_create_page.md b/website/versioned_docs/version-0.80.0/documentation_create_page.md deleted file mode 100644 index 07afe28d..00000000 --- a/website/versioned_docs/version-0.80.0/documentation_create_page.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -title: Create a new page -id: version-0.80.0-documentation_create_page -original_id: documentation_create_page ---- - -For a platform or component page, the fastest way is to make a copy of an existing page and edit it. The [Component overview](https://www.home-assistant.io/components/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages. - -Please honor the [Standards](documentation_standards.md) we have for the documentation. - -If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers. - -```text ---- -layout: page -title: "Awesome Sensor" -description: "home-assistant.io web presence" -date: 2015-06-17 08:00 -sidebar: true -comments: false -sharing: true -footer: true -ha_release: "0.38" -ha_category: Sensor -ha_iot_class: "Local Polling" -ha_qa_scale: silver ---- - -Content... Written in markdown. - -### {% linkable_title Linkable Header %} -... -``` - -Please keep in mind that if the `date:` entry is in the future then the page will not show up. - -Additional keys for the file header: - -- `logo`: Please check the separate section below. -- `ha_release`: The release when the integration was included, e.g., "0.38". If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`. -- `ha_category`: This entry is used to group the integration on the [Components overview](https://www.home-assistant.io/components/). -- `ha_iot_class`: [IoT class](https://www.home-assistant.io/blog/2016/02/12/classifying-the-internet-of-things) is the classifier for the device's behavior. -- `ha_qa_scale`: [Quality scale](https://www.home-assistant.io/docs/quality_scale/) is the representation of the integration's quality. - -There are [pre-defined variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation. - -A couple of points to remember: - -- Document the needed steps to retrieve API keys or access token for the third party service or device if needed. -- Add screenshots to support the user where it makes sense. -- Add the type of the device(s) (incl. firmware) you have tested when you know that there are multiple out there. - -### Configuration - -Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file. - -The **Configuration Variables** section must use the `{% configuration %} ... {% endconfiguration %}` tag. - -```text -{% configuration %} -api_key: - description: The API key to access the service. - required: true - type: string -name: - description: Name to use in the frontend. - required: false - default: The default name to use in the frontend. - type: string -monitored_conditions: - description: Conditions to display in the frontend. - required: true - type: map - keys: - weather: - description: A human-readable text summary. - temperature: - description: The current temperature. -{% endconfiguration %} -``` - -Available keys: - -- **`description:`**: That the variable is about. -- **`required:`**: If the variable is required. - -```text -required: true #=> Required -required: false #=> Optional -required: inclusive #=> Inclusive -required: exclusive #=> Exclusive -required: any string here #=> Any string here -``` -- **`type:`**: The type of the variable. Allowed entries: `boolean`, `string`, `integer`, `float`, `time`, `template`, `device_class`, `icon` or `map`/`list` (for a list of entries). For multiple possibilities use `[string, integer]`. If you use `map`/`list` then should define `keys:` (see the [`template` sensor](https://www.home-assistant.io/components/sensor.template/) for an example). If you use `boolean`, then `default:` must be defined. -- **`default:`**: The default value for the variable. - -### Embedding Code - -You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in back-ticks. - -When you're writing code that is to be executed on the terminal, prefix it with `$`. - -### Templates - -For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) [Jinja](http://jinja.pocoo.org/) is used. Check the [Documentation Standards](documentation_standards.md) for further details. - -If you are don't escape templates then they will be rendered and appear blank on the website. - -### HTML - -The direct usage of HTML is supported but not recommended. The note boxes are an exception. - -```html -

- You need to enable telnet on your router. -

-``` - -### Images, icons and logos - -The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent. - -| Type | Location | -| :----------- |:----------------------------------------------| -| logos | source/images/supported_brands | -| blog | source/images/blog | -| screenshots | source/images/components | - -Not everything (product, component, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/). - -### Linking From The Sidebar - -If you are adding a new page that requires linking from the sidebar, you need to edit the `docs_navigation.html` file in `source/_includes/asides/docs_navigation.html`. diff --git a/website/versioned_docs/version-0.80.0/documentation_index.md b/website/versioned_docs/version-0.80.0/documentation_index.md deleted file mode 100644 index 1f81ce8e..00000000 --- a/website/versioned_docs/version-0.80.0/documentation_index.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Documentation -id: version-0.80.0-documentation_index -original_id: documentation_index ---- - -The user documentation is located at [https://www.home-assistant.io](https://www.home-assistant.io). This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. You work on your change and propose it via a Pull Request (PR). - -Once you've created a Pull Request (PR), you can see a preview of the proposed changes by clicking *Details* against Netlify checker in the checkers section of the PR as soon as deployment is complete. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process of working on the website is no different from working on Home Assistant itself. - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.3.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` -- In your home-assistant.io root directory, run `$ bundle` to install the gems you need. - -Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` -Shortcut for Debian/Ubuntu: `$ sudo apt-get install ruby ruby-dev ruby-bundler ruby-json && bundle` - -Then you can work on the documentation: - -- Fork home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.io). -- Create/edit/update a page. The components/platforms documentation is located in `source/_components/`. `source/_docs/` contains the Home Assistant documentation itself. -- Test your changes to home-assistant.io locally: run `rake preview` and navigate to [http://127.0.0.1:4000](http://127.0.0.1:4000) -- Create a Pull Request (PR) against the **next** branch of home-assistant.io if your documentation is a new feature, platform, or component. -- Create a Pull Request (PR) against the **current** branch of home-assistant.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -It could be necessary that you run `rake generate` prior to `rake preview` for the very first preview. - -Site generated by `rake` is only available locally. If you are developing on a headless machine, use port forwarding: - -```bash -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` -## Speeding up site generation - -Every release we post long changelogs to the website. This slows down generation of the website significantly! We include some tools to temporarily exclude components and blog posts that you're not working on out of the way. - -```bash -bundle exec rake isolate[filename-of-blogpost-or-component] -``` - -When you're done working on the site, run the following command to move the pages back again: - -```bash -bundle exec rake integrate -``` diff --git a/website/versioned_docs/version-0.80.0/documentation_standards.md b/website/versioned_docs/version-0.80.0/documentation_standards.md deleted file mode 100644 index afdb0cf3..00000000 --- a/website/versioned_docs/version-0.80.0/documentation_standards.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -title: Standards -id: version-0.80.0-documentation_standards -original_id: documentation_standards ---- - -To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation. - -## General Documentation - -* The language of the documentation should be American-English. -* Don't put two spaces after a period and avoid the "Oxford comma". -* There is no limit for the line length. You are allowed to write in a flowing text style. This will make it easier to use the GitHub online editor in the future. -* Be objective and not gender favoring, polarizing, race related or religion inconsiderate. -* The case of brand names, services, protocols, components, and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select". -* All headings should use the `{% linkable_title %}` tag. -* Do not use ALL CAPITALS for emphasis - use italics instead - -## Component and Platform Pages - -* The **Configuration Variables** section must use the `{% configuration %}` tag. -* Configuration variables must document the requirement status (`false` or `true`) -* Configuration variables must document the default value, if any. -* Configuration variables must document the accepted value types (see [Configuration variables details](documentation_create_page.md#configuration)) - * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`). -* Use YAML sequence syntax in the sample code if it is supported. -* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated. - * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`. - * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note. -* Component and platform names should be a link to their respective documentation pages. - -Example configuration block - -```yaml -{% configuration %} -some_key: - description: This is a description of what this key is for. - required: false - type: string - default: Optional default value - leave out if there isn't one -{% endconfiguration %} -``` - -## Templates - -* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the `{% raw %}` tag. -* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`. -* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)): - * `friendly_name` - * Single-line templates: - * `value_template` - * `level_template` - * `icon_template` - * Children of `data_template` -* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks): - * Strings inside of templates: - * States - * Entity IDs - * `unit_of_measurement` -* No whitespace around pipe character (`|`) for Jinja2 filters. -* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}). -* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}). -* Do not quote values for: - * `device_class` - * `platform` - * `condition` - * `service` - -## Renaming Pages - -It can happen that a component or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old component/platform name, to the page in a [note](/developers/documentation/create_page/#html). - -```text ---- -... -redirect_from: /getting-started/android/ ---- -``` - -Adding a redirect also applies if you move content around in the [documentation](/docs/). - -## Single vs. Double Quotation Marks - -Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required). - -### Examples - -#### Double Quotes Outside, Single Quotes Inside (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}" -``` - -#### Single Quotes Outside, Double Quotes Inside (Invalid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}' -``` - -#### Multi-Line Template (Valid) - - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: >- - {% if trigger.to_state.name == 'Dale\'s Bedroom' %} - Someone's in your base, killing your noobs! - {% else %} - It's just another door. - {% endif %} -``` - diff --git a/website/versioned_docs/version-0.80.0/entity_sensor.md b/website/versioned_docs/version-0.80.0/entity_sensor.md deleted file mode 100644 index 0bb65d32..00000000 --- a/website/versioned_docs/version-0.80.0/entity_sensor.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Sensor Entity -sidebar_label: Sensor -id: version-0.80.0-entity_sensor -original_id: entity_sensor ---- - -A sensor is a read-only entity that provides some information. Information has a value and optionally, a unit of measurement. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| state | string | **Required** | The value of the sensor. -| unit_of_measurement | string | `None` | The unit of measurement that the sensor is expressed in. -| device_class | string | `None` | Type of sensor. - -### Available device classes - -If specifying a device class, your sensor entity will need to also return the correct unit of measurement. - -| Type | Unit | Description -| ---- | ---- | ----------- -| battery | % | % of battery that is left. -| humidity | % | % of humidity in the air. -| illuminance | lx/lm | Light level. -| temperature | C/F | Temperature. -| pressure | hPa,mbar | Pressure. diff --git a/website/versioned_docs/version-0.80.0/entity_water_heater.md b/website/versioned_docs/version-0.80.0/entity_water_heater.md deleted file mode 100644 index b64bb6a6..00000000 --- a/website/versioned_docs/version-0.80.0/entity_water_heater.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Water Heater Entity -sidebar_label: Water Heater -id: version-0.80.0-entity_water_heater -original_id: entity_water_heater ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| min_temp | float | 110°F | The minimum temperature that can be set. -| max_temp | float | 140°F | The maximum temperature that can be set. -| temperature | float | none | The current temperature in °C or °F. -| operation_mode | string | none | The current operation mode. -| operation_list | list | none | List of possible operation modes. -| away_mode | string | none | The current status of away mode. (on, off) - -The allowed operation modes are specified in the base component and implementations of the water_heater component cannot differ. - -Properties have to follow the units defined in the `unit_system`. - -## States -| State | Description -| ----- | ----------- -| `STATE_ECO` | Energy efficient mode, provides energy savings and fast heating. -| `STATE_ELECTRIC` | Electric only mode, uses the most energy. -| `STATE_PERFORMANCE` | High performance mode. -| `STATE_HIGH_DEMAND` | Meet high demands when water heater is undersized. -| `STATE_HEAT_PUMP` | Slowest to heat, but uses less energy. -| `STATE_GAS` | Gas only mode, uses the most energy. -| `STATE_OFF` | The water heater is off. - -## Methods -### `set_temperature` or `async_set_temperature` -Sets the temperature the water heater should heat water to. - -### `set_operation_mode`or `async_set_operation_mode` -Sets the operation mode of the water heater. Must be in the operation_list. - -### `turn_away_mode_on` or `async_turn_away_mode_on` -Set the water heater to away mode. - -### `turn_away_mode_off` or `async_turn_away_mode_off` -Set the water heater back to the previous operation mode. Turn off away mode. diff --git a/website/versioned_docs/version-0.80.0/frontend_architecture.md b/website/versioned_docs/version-0.80.0/frontend_architecture.md deleted file mode 100644 index c5b731d4..00000000 --- a/website/versioned_docs/version-0.80.0/frontend_architecture.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Home Assistant Frontend Architecture -sidebar_label: Architecture -id: version-0.80.0-frontend_architecture -original_id: frontend_architecture ---- - -The Home Assistant frontend is built using web components. This is a modern web technology allowing us to encapsulate templates, styling and logic into a single file and expose it as an HTML tag in the browser. These componens are composable, allowing a very dynamic and powerful foundation of our application. - -## Structure - -The Home Assistant frontend can be broken up in 4 parts: - -### Bootstrap - -File: `src/entrypoints/core.js` - -This is a very tiny script which is the first thing that is loaded on the page. It is responsible for checking for authentication credentials and setting up the websocket connection with the backend. - -The script allows us to start downloading the data while also downloading the rest of the UI in parallel. - -### App shell - -File: `src/entrypoints/app.js` - -This is everything that is required to render the sidebar and handle the routing. - -### Panels - -Folder: `src/panels/` - -Each page in Home Assistant is a panel. Components can register extra panels to be shown to the user. Examples of panels are "states", "map", "logbook" and "history". - -### More info dialog - -Folder: `src/dialogs/more-info` - -This is a dialog that allows users to see more information about an entity and control its state. - -The more info dialog can be triggered from any component in the app by firing a DOM event `hass-more-info` with as detail `{ entityId: 'light.kitchen' }`. - -## Data Flow - -The frontend leverages the [Websocket API](external_api_websocket.md) and the [Rest API](external_api_rest.md) to interact with Home Assistant. - -The data is made available as the `hass` property which is passed down to every component. The `hass` property contains the whole application state and has methods to call APIs. - -We use a unidirectional data flow (like Flux, Redux). When you make a change in the backend (like turning on a light), the `hass` object will be updated at the root of the application and will be made available to every component that needs it. - -## Routing - -The frontend uses decentralized routing. Each component only knows enough about the routing to know how to handle the part it's responsible for. Further routing is passed down the component tree. - -For example, the `` main component will look at the first part of the url to decide which panel should be loaded. Each panel can have its own mapping between the url and what content to show. - -For the routing, we use the [``](https://www.polymer-project.org/3.0/toolbox/routing) web component. - -## Bundling - -We use Webpack to bundle up the application. We have various gulp scripts to help with generating the icon set and the index.html. - -We're aggresively code splitting our application by leveraging the dynamic import syntax (`import('path/to/some/file.js')`). When encountering an `import()`, Webpack will split the code into different chunks and makes sure that they are loaded when needed. - - diff --git a/website/versioned_docs/version-0.80.0/hassio_addon_communication.md b/website/versioned_docs/version-0.80.0/hassio_addon_communication.md deleted file mode 100644 index 91857241..00000000 --- a/website/versioned_docs/version-0.80.0/hassio_addon_communication.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Add-On Communication -id: version-0.80.0-hassio_addon_communication -original_id: hassio_addon_communication ---- - -There are different ways for communication between add-ons inside Hass.io. - -## Network - -We use an internal network that allows to communicate with every add-on, even to/from Home Assistant, by using its name or alias. Only the add-ons which run on the host network are a bit limited. These can talk with all internal add-ons by their name but all other add-on can't address these add-on by name - using an alias works for both! - -Name/alias are used for communication inside Hass.io. -The name is generated using the following format: `{REPO}_{SLUG}`, e.g., `local_xy` or `3283fh_myaddon`. In this example, `{SLUG}` is defined in an add-ons `config.json`. You can use this name also as DNS name but you need replace the `_` with `-` to have a valid hostname. If an add-on is installed locally, `{REPO}` will be `local`. If the add-on is installed from a Github repository, `{REPO}` is a hashed identifier generated from the GitHub repository's URL (ex: https://github.com/xy/my_hassio_addons). See [here](https://github.com/home-assistant/hassio/blob/587047f9d648b8491dc8eef17dc6777f81938bfd/hassio/addons/utils.py#L17) to understand how this identifier is generated. Note that this identifier is required in certain service calls that use the [Hass.io add-on API][hassio-addon-api]. You can view the repository identifiers for all currently installed add-ons via a GET request to the hassio API `addons` endpoint. - -Use `hassio` for communication with the internal API. - -## Home Assistant - -An add-on can talk to the [Home Assistant API][hass-api] using the internal proxy. That makes it very easy to communicate with the API without knowing the password, port or any other information of the Home Assistant instance. Use this URL: `http://hassio/homeassistant/api` and internal communication is redirected to the right place. The next stept is to add `homeassistant_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN` and use this as Home-Assistant password. - -There is also a proxy for the [Home Assistant Websocket API][hass-websocket]. It works like the API proxy above and requires `HASSIO_TOKEN` as password. Use this URL: `http://hassio/homeassistant/websocket`. - -It is also possible to talk direct to the Home Assistant instance which is named `homeassistant` over the internal network. But you need to know the configuration that is used by the running instance. - -We have severals services for Hass.io inside Home Assistant to run tasks. To send data over STDIN to an add-on use the `hassio.addon_stdin` service. - -## Hass.io API - -To enables calls to the [Hass.io API][hassio-api], add `hassio_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN`. Now you can use the API over the URL: `http://hassio/`. Use the `HASSIO_TOKEN` with header `X-HASSIO-KEY`. It could be that you need also change the Hass.io API role like `hassio_role: default`. - -Add-ons can call some API commands without need set `hassio_api: true`: -- `/homeassistant/api` -- `/homeassistant/websocket` -- `/homeassistant/stream` -- `/addons/self/*` -- `/services*` -- `/discovery*` -- `/info` - -[hass-api]: https://www.home-assistant.io/developers/rest_api/ -[hass-websocket]: https://www.home-assistant.io/developers/websocket_api/ -[hassio-api]: https://github.com/home-assistant/hassio/blob/master/API.md -[hassio-addon-api]: https://github.com/home-assistant/hassio/blob/dev/API.md#restful-for-api-addons diff --git a/website/versioned_docs/version-0.80.0/hassio_addon_config.md b/website/versioned_docs/version-0.80.0/hassio_addon_config.md deleted file mode 100644 index d2cf2467..00000000 --- a/website/versioned_docs/version-0.80.0/hassio_addon_config.md +++ /dev/null @@ -1,209 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.80.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use `jq` inside your shell script to parse this data. However, you might have to install `jq` as a separate package in your container (see `Dockerfile` below). - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -## Add-on Docker file - -All add-ons are based on Alpine Linux 3.6. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | no | List of supported arch: `armhf`, `aarch64`, `amd64`, `i386`. Default all. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| login_backend | bool | no | Allow access to Home Assistent user backend. - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. diff --git a/website/versioned_docs/version-0.80.0/hassio_addon_security.md b/website/versioned_docs/version-0.80.0/hassio_addon_security.md deleted file mode 100644 index d971ff5a..00000000 --- a/website/versioned_docs/version-0.80.0/hassio_addon_security.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Add-on security -id: version-0.80.0-hassio_addon_security -original_id: hassio_addon_security ---- - -Hass.io rates every add-on based on the wanted rights. An add-on with a rating of 6 is very secure. If an add-on has a rating of 1, you shouldn't run this add-on unless you are 100% sure that you can trust the source. - -## API Role - -For access to Hass.io API you need define a role or you run in default mode. This is only required for Hass.io API not Home Assistant proxy. Any of the role have also the default API calls inheret for that are no settings are required. - -### Available Roles - -| Role | Description | -|------|-------------| -| default | Have access to all `info` calls | -| homeassistant | Can access to all Home Assistant API endpoints | -| backup | Can access to all snapshot API endpoints | -| manager | Is for Add-ons they run CLIs and need extended rights | -| admin | Have access to every API call. That is the only one they can disable/enable the Add-on protection mode | - -## Protection - -Default, all add-ons run in protection enabled mode. This mode prevents the add-on from getting any rights on the system. If an add-on requires more rights, you can disable this protection via the API add-on options for that add-on. But be carful, an add-on with disabled protection can destroy your system! - -## Making a secure add-on - -As a developer, follow the following best practices to make your add-on secure: - -- Don't run on host network -- Create an AppArmor profile -- Map folders read only if you don't need write access -- If you need any API access, make sure you that you not grant to highest permission if you don't need it diff --git a/website/versioned_docs/version-0.80.0/hassio_debugging.md b/website/versioned_docs/version-0.80.0/hassio_debugging.md deleted file mode 100644 index f573f26f..00000000 --- a/website/versioned_docs/version-0.80.0/hassio_debugging.md +++ /dev/null @@ -1,50 +0,0 @@ ---- -title: Debugging Hass.io -id: version-0.80.0-hassio_debugging -original_id: hassio_debugging ---- - -> This section is not for users. Use the [SSH add-on] to SSH into Hass.io. This is for developers of Hass.io. Do not ask for support if you are using these options. - -[SSH add-on]: https://www.home-assistant.io/addons/ssh/ - -The following debug tips and tricks are for people who are running the Hass.io image and are working on the base image. If you use the generic Linux installer script, you should be able to access your host and logs as per your host. - -## SSH access to the host - -### resinOS based Hass.io (deprecated) -Create an `authorized_keys` file containing your public key, and place it in the root of the boot partition of your SD card. Once the device is booted, you can access your device as root over SSH on port 22222. - -### HassOS based Hass.io -Use a USB drive formatted with FAT, ext4, or NTFS and name it CONFIG (case sensitive). Create an `authorized_keys` file containing your public key, and place it in the root of the USB drive. From the UI, navigate to the hass.io system page and choose "Import from USB". You can now access your device as root over SSH on port 22222. Alternatively, the file will be imported from the USB when the hass.io device is rebooted. - -### Generating Keys -Windows instructions how to generate and use private/public keys with Putty are [here][windows-keys]. Instead of the droplet instructions, add the public key as per above instructions. - -Alternative instructions, for Mac, Windows and Linux can be found [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#platform-mac). - -Follow steps 1-4 under 'Generating a new SSH key' (The other sections are not applicable to Hass.io and can be ignored.) - -Step 3 in the link above, shows the path to the private key file `id_rsa` for your chosen operating system. Your public key, `id_rsa.pub`, is saved in the same folder. Next, select all text from text box "Public key for pasting into OpenSSH authorized_keys file" and save it to the root of your SD card as `authorized_keys`. - -> Make sure when you are copying the public key to the root of the /resin-boot partition of the SD card that you rename the file correctly to `authorized_keys` with no `.pub` file extension. - -You should then be able to SSH into your Hass.io device. On mac/linux, use: -``` -ssh root@hassio.local -p 22222 -``` - -## Checking the logs - -```bash -# Logs from the supervisor service on the Host OS -journalctl -f -u hassos-supervisor.service - -# Hass.io supervisor logs -docker logs hassos_supervisor - -# Home Assistant logs -docker logs homeassistant -``` - -[windows-keys]: https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-putty-on-digitalocean-droplets-windows-users diff --git a/website/versioned_docs/version-0.80.0/integration_quality_scale_index.md b/website/versioned_docs/version-0.80.0/integration_quality_scale_index.md deleted file mode 100644 index ccdd932a..00000000 --- a/website/versioned_docs/version-0.80.0/integration_quality_scale_index.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Integration Quality Scale -sidebar_label: Introduction -id: version-0.80.0-integration_quality_scale_index -original_id: integration_quality_scale_index ---- - -The Integration Quality Scale scores each integration based on the code quality and user experience. Each level of the quality scale consists of a list of requirements. If an integration matches all requirements, it's considered to have reached that level. - -> Suggestions for changes can be done by creating an issue in the [architecture repo](https://github.com/home-assistant/architecture/issues/). - -# No score - -This integration passes the bare minimum requirements to become part of the index. - - - Satisfy all requirements for [creating components](creating_component_code_review.md) and [creating platforms](creating_platform_code_review.md). - - Configurable via `configuration.yaml` - -# Silver 🥈 - -This integration is able to cope when things go wrong. It will not print any exceptions nor will it fill the log with retry attempts. - -- Set an appropriate `SCAN_INTERVAL` (if a polling integration) -- Raise `PlatformNotReady` if unable to connect during platform setup (if appropriate) -- Handles expiration of auth credentials. Refresh if possible or print correct error and fail setup. If based on a config entry, should trigger a new config entry flow to re-authorize. -- Handles internet unavailable. Log a warning once when unavailable, log once when reconnected. -- Handles device/service unavailable. Log a warning once when unavailable, log once when reconnected. -- Set `available` property to `False` if appropriate ([docs](entity_index.md#generic-properties)) -- Entities have unique ID (if available) ([docs](entity_registry_index.md#unique-id-requirements)) - -# Gold 🥇 - -This is a solid integration that is able to survive poor conditions and can be configured via the user interface. - -- Configurable via config entries. - - Don't allow configuring already configured device/service (example: no 2 entries for same hub) - - Tests for the config flow - - Discoverable (if available) -- Entities have device info (if available) ([docs](device_registry_index.md#defining-devices)) -- States are translated in the frontend (text-based sensors only, [docs](internationalization_index.md)) -- Tests for reading data from/controlling the integration ([docs](development_testing.md)) -- Has a code owner - -# Platinum 🏆 - -Best of the best. The integration is completely async, meaning it's super fast. Integrations that reach platinum level will require approval by the code owner for each PR. - -- Set appropriate `PARALLEL_UPDATES` constant -- Support config entry unloading (called when config entry is removed) -- Integration + dependency are async -- Uses aiohttp and allows passing in websession (if making HTTP requests) - -# Internal 🏠 - -Integrations which are part of Home Assistant are not rated but marked as **internal**. - diff --git a/website/versioned_docs/version-0.81.0/asyncio_index.md b/website/versioned_docs/version-0.81.0/asyncio_index.md deleted file mode 100644 index 0beefbde..00000000 --- a/website/versioned_docs/version-0.81.0/asyncio_index.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Asynchronous Programming -sidebar_label: Introduction -id: version-0.81.0-asyncio_index -original_id: asyncio_index ---- - -On September 29, 2016 we released [Home Assistant 0.29][0.29] as part of our bi-weekly release schedule. This release introduced a complete overhaul of the core spearheaded by [Ben Bangert][ben]. - -The old core was set up like a “traditional” threaded application. Each resource that was not thread safe (ie. the state of entities) would be protected by a lock. This caused a lot of waiting and potential inconsistency because a task could now end up waiting halfway through its job until some resource got freed. - -Our new core is based on Python’s built-in **asyncio** module. Instead of having all threads have access to the core API objects, access is now limited to a special thread called the *event loop*. All components will now schedule themselves as a task to be executed by the event loop. This gives us the guarantee that only a single task is executed at the same time, meaning we no longer need any locks. - -The only problem with running everything inside the event loop is when a task does blocking I/O; something most third-party Python libraries do. For example, while requesting new information from a device, the core will stop running until we get a response from the device. To handle this, a task is able to suspend itself until the response is available, after which it will be enqueued in the event loop to process the result. - -For a task to be able to suspend itself, all code that it calls must support this capability. In practice, this would mean that each device integration will need a full rewrite of the library that offers the integration! As this is something that cannot be achieved, ever, a 100% backwards compatible API has been added so that no platform will require updating. - -The backwards compatible API schedules a task in a different thread and blocks that thread until the task has been processed by the event loop. - -[0.29]: https://www.home-assistant.io/blog/2016/09/29/async-sleepiq-emoncms-stocks/ -[ben]: https://github.com/bbangert/ diff --git a/website/versioned_docs/version-0.81.0/auth_api.md b/website/versioned_docs/version-0.81.0/auth_api.md deleted file mode 100644 index 79b32e4a..00000000 --- a/website/versioned_docs/version-0.81.0/auth_api.md +++ /dev/null @@ -1,255 +0,0 @@ ---- -title: Authentication API -sidebar_label: API -id: version-0.81.0-auth_api -original_id: auth_api ---- - -This page will describe the steps required for your application to authorize against and integrate with Home Assistant instances. [See a demo](https://hass-auth-demo.glitch.me) powered by our helper lib [home-assistant-js-websocket](https://github.com/home-assistant/home-assistant-js-websocket). - -Each user has their own instance of Home Assistant which gives each user control over their own data. However, we also wanted to make it easy for third party developers to create applications that allow users to integrate with Home Assistant. To achieve this, we have adopted the [OAuth 2 specification][oauth2-spec] combined with the [OAuth 2 IndieAuth extension][indieauth-spec] for generating clients. - -## Clients - -Before you can ask the user to authorize their instance with your application, you will need a client. In traditional OAuth2, the server needs to generate a client before a user can authorize. However, as each server belongs to a user, we've adopted a slightly different approach from [IndieAuth][indieauth-clients]. - -The client ID you need to use is the website of your application. The redirect url has to be of the same host and port as the client ID. For example: - - - client id: `https://www.my-application.io` - - redirect uri: `https://www.my-application.io/hass/auth_callback` - -If you require a different redirect url (ie, if building a native app), you can add an HTML tag to the content of the website of your application (the client ID) with an approved redirect url. For example, add this to your site to whitelist redirect uri `hass://auth`: - -```html - -``` - -Home Assistant will scan the first 10kB of a website for link tags. - -## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) - -> All example URLs here are shown with extra spaces and new lines for display purposes only. - -The authorize url should contain `client_id` and `redirect_uri` as query parameters. - -``` -http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2F%3Fauth_callback%3D1 -``` - -Optionally you can also include a `state` parameter, this will be added to the redirect uri. The state is perfect to store the instance url that you are authenticating with. Example: - -``` -http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2Fauth_callback& - state=http%3A%2F%2Fhassio.local%3A8123 -``` - -The user will navigate to this link and be presented with instructions to log in and authorize your application. Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code and state as part of the query parameters. Example: - -``` -https://hass-auth-demo.glitch.me/auth_callback - code=12345& - state=http%3A%2F%2Fhassio.local%3A8123 -``` - -This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section). - -## Token - -The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. In thee case of refresh token, the token endpoint is also capable of revoking a token. - -All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`. - -### Authorization code - -> All requests to the token endpoint need to contain the exact same client ID as was used to redirect the user to the authorize endpoint. - -Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is: - -``` -grant_type=authorization_code& -code=12345& -client_id=https%3A%2F%2Fhass-auth-demo.glitch.me -``` - -The return response will be an access and refresh token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "refresh_token": "IJKLMNOPQRST", - "token_type": "Bearer" -} -``` - -The access token is a short lived token that can be used to access the API. The refresh token can be used to fetch new access tokens. The `expires_in` value is seconds that the access token is valid. - -An HTTP status code of 400 will be returned if an invalid request has been issued. The HTTP status code will be 403 if a token is requested for an inactive user. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Refresh token - -Once you have retrieved a refresh token via the grant type `authorization_code`, you can use it to fetch new access tokens. The request body is: - -``` -grant_type=refresh_token& -refresh_token=IJKLMNOPQRST& -client_id=https%3A%2F%2Fhass-auth-demo.glitch.me -``` - -The return response will be an access token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "token_type": "Bearer" -} -``` - -An HTTP status code of 400 will be returned if an invalid request has been issued. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Revoking a refresh token - -> client_id is not need for revoke refresh token - -The token endpoint is also capable of revoking a refresh token. Revoking a refresh token will immediately revoke the refresh token and all access tokens that it has ever granted. To revoke a refresh token, make the following request: - -``` -token=IJKLMNOPQRST& -action=revoke -``` - -The request will always respond with an empty body and HTTP status 200, regardless if the request was successful. - -## Long-lived access token - -A long-lived access token is usually used for 3rd party API calls and webhook-ish integrations. To generate a long-lived access token, an active websocket connection has to be established. - -Send websocket command `auth/long_lived_access_token` will create a long-lived access token for current user. Access token will not be saved in Home Assistant. User need to record the token in secure place. - -```json -{ - "id": 11, - "type": "auth/long_lived_access_token", - "client_name": "GPS Logger", - "client_icon": null, - "lifespan": 365 -} -``` - -Result will be a long-lived access token: - -```json -{ - "id": 11, - "type": "result", - "success": true, - "result": "ABCDEFGH" -} -``` - -## Making authenticated requests - -Once you have an access token, you can make authenticated requests to the Home Assistant APIs. - -For the websocket connection, pass the access token in the [authentication message](https://developers.home-assistant.io/docs/en/external_api_websocket.html#authentication-phase). - -For HTTP requests, pass the token type and access token as the authorization header: - -``` -Authorization: Bearer ABCDEFGH -``` - -### Example: cURL - -```shell -curl -X GET \ - https://your.awesome.home/api/error/all \ - -H 'Authorization: Bearer ABCDEFGH' -``` - -### Example: Python - -```python -import requests - -url = "https://your.awesome.home/api/error/all" -headers = { - 'Authorization': "Bearer ABCDEFGH", -} -response = requests.request('GET', url, headers=headers) - -print(response.text) -``` - -### Example: NodeJS -```JavaScript -fetch('https://your.awesome.home/api/error/all', { - headers: { Authorization: 'Bearer ABCDEFGH' } -}).then(function (response) { - if (!response.ok) { - return Promise.reject(response); - } - return response.text(); -}).then(function (body ) { - console.log(body); -}); -``` - -If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and so the user is no longer logged in. You should clear the user's data and ask the user to authorize again. - -[oauth2-spec]: https://tools.ietf.org/html/rfc6749 -[indieauth-spec]: https://indieauth.spec.indieweb.org/ -[indieauth-clients]: https://indieauth.spec.indieweb.org/#client-identifier - -## Signed paths - -Sometimes you want a user to make a GET request to Home Assistant to download data. In this case the normal auth system won't do, as we can't link the user to an API with the auth header attached to it. In that case, a signed path can help. - -A signed path is a normal path on our server, like `/api/states`, but with an attached secure authentication signature. The user is able to navigate to this path and will be authorised as the access token that created the signed path. Signed paths can be created via the websocket connection and are meant to be shortlived. The default expiration is 30 seconds. - -To get a signed path, send the following command: - -```js -{ - "type": "auth/sign_path", - "path": "/api/states", - // optional, expiration time in seconds. Defaults to 30 seconds - "expires": 20 -} -``` - -The response will contain the signed path: - -```js -{ - "path": "/api/states?authSig=ABCDEFGH" -} -``` - -Some things to note about a signed path: - - - If the refresh token is deleted, the signed url is no longer valid. - - If the user is deleted, the signed url is no longer valid (because the refresh token will be deleted). - - If Home Assistant is restarted, the signed url is no longer valid. - - Access is only validated when the request is received. If a response takes longer than the expiration time (ie, downloading a large file), the download will continue after the expiration date has passed. diff --git a/website/versioned_docs/version-0.81.0/auth_auth_module.md b/website/versioned_docs/version-0.81.0/auth_auth_module.md deleted file mode 100644 index 7a34ab20..00000000 --- a/website/versioned_docs/version-0.81.0/auth_auth_module.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Multi-factor Authentication Modules -id: version-0.81.0-auth_auth_module -original_id: auth_auth_module ---- - -Multi-factor Authentication Modules are used in conjunction with [Authentication Provider](auth_auth_provider.html) to provide a fully configurable authentication framework. Each MFA module may provide one multi-factor authentication function. User can enable multiple mfa modules, but can only select one module in login process. - -## Defining an mfa auth module - -> We currently only support built-in mfa auth modules. Support for custom auth modules might arrive in the future. - -Multi-facor Auth modules are defined in `homeassistant/auth/mfa_modules/.py`. The auth module will need to provide an implementation of the `MultiFactorAuthModule` class. - -For an example of a fully implemented auth module, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/mfa_modules/insecure_example.py). - -Multi-factor Auth modules shall extend the following methods of `MultiFactorAuthModule` class. - -| method | Required | Description -| ------ | -------- | ----------- -| `@property def input_schema(self)` | Yes | Return a schema defined the user input form. -| `async def async_setup_flow(self, user_id)` | Yes | Return a SetupFlow to handle the setup workflow. -| `async def async_setup_user(self, user_id, setup_data)` | Yes | Set up user for use this auth module. -| `async def async_depose_user(self, user_id)` | Yes | Remove user information from this auth module. -| `async def async_is_user_setup(self, user_id)` | Yes | Return whether user is set up. -| `async def async_validate(self, user_id, user_input)` | Yes | Given a user_id and user input, return validation result. -| `async def async_initialize_login_mfa_step(self, user_id)` | No | Will be called once before display the mfa step of login flow. This is not initialization for the MFA module but the mfa step in login flow. - -## Setup Flow - -Before user can use a multi-factor auth module, it has to be enabled or set up. All available modules will be listed in user profile page, user can enable the module he/she wants to use. A setup data entry flow will guide user finish the necessary steps. - -Each MFA module need to implement a setup flow handler extends from `mfa_modules.SetupFlow` (if only one simple setup step need, `SetupFlow` can be used as well). For example for Google Authenticator (TOTP, Time-based One Time Password) module, the flow will need to be: -- Generate a secret and store it on instance of setup flow -- Return `async_show_form` with a QR code in the description (injected as base64 via `description_placeholders`) -- User scans code and enters a code to verify it scanned correctly and clock in synced -- TOTP module saved the secret along with user_id, module is enabled for user - -## Workflow - -> TODO: draw a diagram - -User == select auth provider ==> LoginFlow.init == input/validate username/password ==> LoginFlow.finish ==> if user enabled mfa ==> LoginFlow.select_mfa_module ==> initialize(optional) ==> LoginFlow.mfa == input/validate MFA code ==> LoginFlow.finish ==> Done - -## Configuration example - -```yaml -# configuration.xml -homeassistant: - auth_providers: - - type: homeassistant - - type: legacy_api_password - auth_mfa_modules: - - type: totp - - type: insecure_example - users: [{'user_id': 'a_32_bytes_length_user_id', 'pin': '123456'}] -``` - -In this example, user will first select from `homeassistant` or `legacy_api_password` auth provider. For `homeassistant` auth provider, user will first input username/password, if that user enabled both `totp` and `insecure_example`, then user need select one auth module, then input Google Authenticator code or input pin code base on the selection. - -> insecure_example is only for demo purpose, please do not use it in production. - -## Validation session - -Not like auth provider, auth module use session to manage the validation. After auth provider validated, mfa module will create a validation session, include an experiation time and user_id from auth provider validate result. Mutli-factor auth module will not only verify the user input, but also verify the session is not expired. The validation session data is stored in your configuration directory. diff --git a/website/versioned_docs/version-0.81.0/development_index.md b/website/versioned_docs/version-0.81.0/development_index.md deleted file mode 100644 index 0d3995aa..00000000 --- a/website/versioned_docs/version-0.81.0/development_index.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Starting with Development -sidebar_label: Introduction -id: version-0.81.0-development_index -original_id: development_index ---- - -Home Assistant is built from the ground up to be easily extensible using components. Home Assistant uses [Python 3](https://www.python.org/) for the backend and [Polymer (Web components)](https://www.polymer-project.org/) for the frontend. - -Home Assistant is open-source and licensed under [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0). Here are links to the source: - - - [home-assistant](https://github.com/home-assistant/home-assistant): Python server backend. - - [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer): Polymer UI. - -For those new to contributing to open source software, make sure you are familiar with all of the tools and concepts used in Home Assistant before you start. - -When contributing Home Assistant code: - - [Github](https://guides.github.com/activities/hello-world/) - - [Pip and Virtual Environments](https://www.dabapps.com/blog/introduction-to-pip-and-virtualenv-python/) - - [Python 3](https://www.python.org/) - - [Pylint](https://www.pylint.org) - - [Flake8](http://flake8.pycqa.org/en/latest/) - - [Tox](http://tox.readthedocs.org/en/latest/) - - [TravisCl](https://travis-ci.org/) - -Home Assistant follows [Debian Stable](https://packages.debian.org/stable/python/python3) for the minimum Python version, which is currently [Python 3.5.3](https://www.python.org/downloads/release/python-353/). - -When contributing 3rd Party code to be used by Home Assistant: - - [Publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) diff --git a/website/versioned_docs/version-0.81.0/development_testing.md b/website/versioned_docs/version-0.81.0/development_testing.md deleted file mode 100644 index 2a6fd887..00000000 --- a/website/versioned_docs/version-0.81.0/development_testing.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Testing your code -id: version-0.81.0-development_testing -original_id: development_testing ---- - -As it states in the [Style guidelines section](development_guidelines.md) all code is checked to verify the following: - -- All the unit tests pass -- All code passes the checks from the linting tools - -Local testing is done using Tox, which has been installed as part of running `script/setup` in the [virtual environment](development_environment.md). To start the tests, activate the virtual environment and simply run the command: - -```bash -$ tox -``` -**Important:** Run `tox` before you create your pull request to avoid annoying fixes. - -Running Tox will run unit tests against the locally available Pythons, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one tox target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py36` runs unit tests only on Python 3.6. - -Tox uses virtual environments under the hood to create isolated testing environments. The tox virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell Tox to recreate the virtual environments. - -OSX users may see an `Error creating virtualenv` when runnng `tox`. If this occurs, install the [tox-venv](https://pypi.org/project/tox-venv/) package using the command `pip install tox-venv` and try again. - -### Adding new dependencies to test environment - -If you are working on tests for a component or platform and you need the dependencies available inside the Tox environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments. - -### Running single tests using Tox - -You can pass arguments via Tox to py.test to be able to run single test suites or test files. Replace `py36` with the Python version that you use. - -```bash -# Stop after the first test fails -$ tox -e py36 -- tests/test_core.py -x -# Run test with specified name -$ tox -e py36 -- tests/test_core.py -k test_split_entity_id -# Fail a test after it runs for 2 seconds -$ tox -e py36 -- tests/test_core.py --timeout 2 -# Show the 10 slowest tests -$ tox -e py36 -- tests/test_core.py --duration=10 -``` - -### Testing outside of Tox - -Running tox will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without Tox, you'll need to install the test dependencies into your Python environment: - -```bash -$ pip3 install -r requirements_test_all.txt -``` - -Now that you have all test dependencies installed, you can run tests on individual files: - -```bash -$ flake8 homeassistant/core.py -$ pylint homeassistant/core.py -$ pydocstyle homeassistant/core.py -$ py.test tests/test_core.py -``` - -You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script: - -```bash -$ script/lint -``` - -### Preventing Linter Errors - -Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them! - -```bash -$ pip3 install flake8 flake8-docstrings -$ flake8 --install-hook=git -``` - -The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8. - -### Notes on PyLint and PEP8 validation - -If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member. diff --git a/website/versioned_docs/version-0.81.0/documentation_index.md b/website/versioned_docs/version-0.81.0/documentation_index.md deleted file mode 100644 index 5630bf27..00000000 --- a/website/versioned_docs/version-0.81.0/documentation_index.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Documentation -id: version-0.81.0-documentation_index -original_id: documentation_index ---- - -The user documentation is located at [https://www.home-assistant.io](https://www.home-assistant.io). This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. You work on your change and propose it via a Pull Request (PR). - -Once you've created a Pull Request (PR), you can see a preview of the proposed changes by clicking *Details* against Netlify checker in the checkers section of the PR as soon as deployment is complete. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process of working on the website is no different from working on Home Assistant itself. - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.3.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` -- In your home-assistant.io root directory, run `$ bundle` to install the gems you need. - -Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` -Shortcut for Debian/Ubuntu: `$ sudo apt-get install ruby ruby-dev ruby-bundler ruby-json && bundle` - -Then you can work on the documentation: - -- Fork home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.io). -- Create/edit/update a page. The components/platforms documentation is located in `source/_components/`. `source/_docs/` contains the Home Assistant documentation itself. -- Test your changes to home-assistant.io locally: run `bundle exec rake preview` and navigate to [http://127.0.0.1:4000](http://127.0.0.1:4000) -- Create a Pull Request (PR) against the **next** branch of home-assistant.io if your documentation is a new feature, platform, or component. -- Create a Pull Request (PR) against the **current** branch of home-assistant.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -It could be necessary that you run `bundle exec rake generate` prior to `bundle exec rake preview` for the very first preview. - -Site generated by `bundle exec rake` is only available locally. If you are developing on a headless machine, use port forwarding: - -```bash -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` -## Speeding up site generation - -Every release we post long changelogs to the website. This slows down generation of the website significantly! We include some tools to temporarily exclude components and blog posts that you're not working on out of the way. - -```bash -bundle exec rake isolate[filename-of-blogpost-or-component] -``` - -When you're done working on the site, run the following command to move the pages back again: - -```bash -bundle exec rake integrate -``` diff --git a/website/versioned_docs/version-0.81.0/external_api_rest.md b/website/versioned_docs/version-0.81.0/external_api_rest.md deleted file mode 100644 index e96e7684..00000000 --- a/website/versioned_docs/version-0.81.0/external_api_rest.md +++ /dev/null @@ -1,517 +0,0 @@ ---- -title: REST API -id: version-0.81.0-external_api_rest -original_id: external_api_rest ---- - -Home Assistant runs a web server accessible on port 8123. - -* http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -* http://IP_ADDRESS:8123/api/ is a Rest API. - -The API accepts and returns only JSON encoded objects. All API calls have to be accompanied by the header `X-HA-Access: YOUR_PASSWORD` (YOUR_PASSWORD as specified in your `configuration.yaml` file in the [`http:` section](https://www.home-assistant.io/components/http/)). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```bash -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. = - -```python -from requests import get - -url = 'http://localhost:8123/ENDPOINT' -headers = { - 'Authorization': 'Bearer ABCDEFGH', - 'content-type': 'application/json', -} - -response = get(url, headers=headers) -print(response.text) -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on a single entity -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates the current state of an entity. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance.
- -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` diff --git a/website/versioned_docs/version-0.81.0/external_api_server_sent_events.md b/website/versioned_docs/version-0.81.0/external_api_server_sent_events.md deleted file mode 100644 index 71970099..00000000 --- a/website/versioned_docs/version-0.81.0/external_api_server_sent_events.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Server-sent events -id: version-0.81.0-external_api_server_sent_events -original_id: external_api_server_sent_events ---- - -The [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) feature is a one-way channel from your Home Assistant server to a client which is acting as a consumer. For a bi-directional streaming API, check out the [WebSocket API](external_api_websocket.md). - -The URI that is generating the data is `/api/stream`. - -A requirement on the client-side is existing support for the [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) interface. - -There are various ways to access the stream. If you have not set an `api_password` in the [`http`](https://www.home-assistant.io/components/http/) section of your `configuration.yaml` file then you use your modern browser to read the messages. A command-line option is `curl`: - -```bash -$ curl -X GET -H 'Authorization: Bearer ABCDEFGH' \ - -H "Content-Type: application/json" http://localhost:8123/api/stream -``` - -> Will no longer work with the new Authentication system. - -You can create a convenient view for this by creating an HTML file (`sse.html`) in the `www` folder of your Home Assistant configuration directory (`.homeassistant`). Paste this snippet into the file: - -```html - - - -

Getting Home Assistant server events

-
- - - -``` - -Visit [http://localhost:8123/local/sse.html](http://localhost:8123/local/sse.html) to see the stream of events. - -## Examples - -A simple way to consume server-sent events is to use a command-line http client like [httpie](https://httpie.org/). Installation info is on the site (if you use Homebrew, it's `brew install httpie`). Once installed, run this snippet from your terminal: - -```bash -$ http --stream http://localhost:8123/api/stream 'Authorization:Bearer ABCDEFGH' content-type:application/json -``` - -### Website - -> Will no longer work with the new Authentication system. - -The [home-assistant-sse](https://github.com/fabaff/home-assistant-sse) repository contains a more advanced example. - -### Python - -> Will no longer work with the new Authentication system. - -If you want to test the server-sent events without creating a website, the Python module [`sseclient` ](https://pypi.python.org/pypi/sseclient/) can help. To install (assuming Python and pip3 are already installed): - -```bash -$ pip3 install sseclient -``` - -A simple script to consume SSE in Python looks like this: - -```python -from sseclient import SSEClient - -messages = SSEClient('http://localhost:8123/api/stream?api_password=YOUR_PASSWORD') -for msg in messages: - print(msg) -``` diff --git a/website/versioned_docs/version-0.81.0/hassio_addon_config.md b/website/versioned_docs/version-0.81.0/hassio_addon_config.md deleted file mode 100644 index 163abec1..00000000 --- a/website/versioned_docs/version-0.81.0/hassio_addon_config.md +++ /dev/null @@ -1,209 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.81.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use `jq` inside your shell script to parse this data. However, you might have to install `jq` as a separate package in your container (see `Dockerfile` below). - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -## Add-on Docker file - -All add-ons are based on Alpine Linux 3.6. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | no | List of supported arch: `armhf`, `aarch64`, `amd64`, `i386`. Default all. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| auth_api | bool | no | Allow access to Home Assistent user backend. - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. diff --git a/website/versioned_docs/version-0.82.0/architecture_hassio.md b/website/versioned_docs/version-0.82.0/architecture_hassio.md deleted file mode 100644 index 937aa7b1..00000000 --- a/website/versioned_docs/version-0.82.0/architecture_hassio.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Hass.io Architecture -sidebar_label: Hass.io -id: version-0.82.0-architecture_hassio -original_id: architecture_hassio ---- - -![Architecture overview of Hass.io](/img/en/architecture/hassio.png) - -## Host Control (HC) - -This is a daemon running on the host machine that allows the supervisor to control certain aspects of the host OS: - - - Power cycle (restart, turn off) - - Manage network settings - - Local updates - -## Host - -Our pre-build images are based on [HassOS] which is based on [BuildRoot]. Any Linux machine can be turned into a Hass.io host by running [the installer][linux]. - -## Supervisor - -The supervisor offers an API to manage the host and running the Docker containers. - -## Configuration panel - -The configuration panel lives inside the supervisor but is accessible via the Home Assistant user interface. The configuration panel allows the user to manage the installation. - -[HassOS]: https://github.com/home-assistant/hassos -[BuildRoot]: https://buildroot.org/ -[linux]: https://www.home-assistant.io/hassio/installation/#alternative-install-on-generic-linux-server diff --git a/website/versioned_docs/version-0.82.0/asyncio_working_with_async.md b/website/versioned_docs/version-0.82.0/asyncio_working_with_async.md deleted file mode 100644 index 9a12049f..00000000 --- a/website/versioned_docs/version-0.82.0/asyncio_working_with_async.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: Working with Async -id: version-0.82.0-asyncio_working_with_async -original_id: asyncio_working_with_async ---- - -Although we have a backwards compatible API, using the async core directly will be a lot faster. Most core components have already been rewritten to leverage the async core. This includes the EntityComponent helper (foundation of light, switch, etc), scripts, groups and automation. - -## Interacting with the core - -[All methods in the Home Assistant core][dev-docs] are implemented in two flavors: an async version and a version to be called from other threads. The versions for other are merely wrappers that call the async version in a threadsafe manner. - -So if you are making calls to the core (the hass object) from within a callback or coroutine, use the methods that start with async_. If you need to call an async_ function that is a coroutine, your task must also be a coroutine. - -## Implementing an async component - -To make a component async, implement an async_setup. - -```python -def setup(hass, config): - # Setup your component outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup(hass, config): - # Setup your component inside of the event loop. -``` - -## Implementing an async platform - -For platforms we support async setup. Instead of setup_platform you need to have a coroutine async_setup_platform. - -```python -setup_platform(hass, config, add_entities, discovery_info=None): - # Setup your platform outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup_platform(hass, config, async_add_entities, - discovery_info=None): - # Setup your platform inside of the event loop -``` - -The only difference with the original parameters is that the `add_entities` function has been replaced by the async friendly callback `async_add_entities`. - -## Implementing an async entity - -You can make your entity async friendly by converting your update method to be async. This requires the dependency of your entities to also be async friendly! - -```python -class MyEntity(Entity): - def update(self): - """Retrieve latest state.""" - self._state = fetch_state() -``` - -Will turn into: - -```python -class MyEntity(Entity): - async def async_update(self): - """Retrieve latest state.""" - self._state = await async_fetch_state() -``` - -Make sure that all properties defined on your entity do not result in I/O being done. All data has to be fetched inside the update method and cached on the entity. This is because these properties are read from within the event loop and thus doing I/O will result in the core of Home Assistant waiting until your I/O is done. - -## Calling async functions from threads - -Sometimes it will happen that you’re in a thread and you want to call a function that is only available as async. Home Assistant includes a few async helper utilities to help with this. - -In the following example, `say_hello` will schedule `async_say_hello` and block till the function has run and get the result back. - -```python -from homeassistant.util.async_ import run_coroutine_threadsafe - -def say_hello(hass, target): - return run_coroutine_threadsafe( - async_say_hello(hass, target), hass.loop).result() - -async def async_say_hello(hass, target): - return "Hello {}!".format(target) -``` - -## Calling sync functions from async - -If you are running inside an async context, it might sometimes be necessary to call a sync function. Do this like this: - -```python -# hub.update() is a sync function. -result = await hass.async_add_executor_job(hub.update) -``` - -## Starting independent task from async - -If you want to spawn a task that will not block the current async context, you can choose to create it as a task on the event loop. It will then be executed in parallel. - -```python -hass.async_create_task(async_say_hello(hass, target)) -``` - - -[dev-docs]: https://dev-docs.home-assistant.io/en/master/api/core.html -[dev-docs-async]: https://dev-docs.home-assistant.io/en/dev/api/util.html#module-homeassistant.util.async diff --git a/website/versioned_docs/version-0.82.0/auth_permissions.md b/website/versioned_docs/version-0.82.0/auth_permissions.md deleted file mode 100644 index e6e4f34a..00000000 --- a/website/versioned_docs/version-0.82.0/auth_permissions.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: Permissions -id: version-0.82.0-auth_permissions -original_id: auth_permissions ---- - -> This is an experimental feature that is not enabled or enforced yet - -Permissions limit the things a user has access to or can control. Permissions are attached to groups, of which a user can be a member. The combined permissions of all groups a user is a member of decides what a user can and cannot see or control. - -Permissions do not apply to the user that is flagged as "owner". This user will always have access to everything. - -## General permission structure - -Policies are dictionaries that at the root level consist of different categories of permissions. In the current implementation this is limited to just entities. - -```python -{ - "entities": … -} -``` - -Each category can further split into subcategories that describe parts of that category. - -```python -{ - "entities": { - "domains": …, - "entity_ids": … - } -} -``` - -If a category is omitted, the user will not have permission to that category. - -When defining a policy, any dictionary value at any place can be replaced with `True` or `None`. `True` means that permission is granted and `None` means use default, which is deny access. - -## Entities - -Entity permissions can be set on a per entity and per domain basis using the subcategories `entity_ids` and `domains`. Granting access to an entity means a user will be able to read the state and control it. - -If an entity is specified in both the `entity_ids` and `domains` subcategory, the `entity_ids` result will be used, unless it is `None`. In the following example, the user will have access to all light entities except for `light.kitchen`. - -```python -{ - "entities": { - "domains": { - "light": True - }, - "entity_ids": { - "light.kitchen": False - } - } -} -``` - -## Merging policies - -If a user is a member of multiple groups, the groups permission policies will be combined into a single policy at runtime. When merging policies, we will look at each level of the dictionary and compare the values for each source using the following methodology: - -1. If any of the values is `True`, the merged value becomes `True`. -2. If any value is a dictionary, the merged value becomes a dictionary created by recursively checking each value using this methodology. -3. If all values are `None`, the merged value becomes `None`. - -Let's look at an example: - -```python -{ - "entities": { - "entity_ids": { - "light.kitchen": True - } - } -} -``` - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -Once merged becomes - -```python -{ - "entities": { - "entity_ids": True - } -} -``` diff --git a/website/versioned_docs/version-0.82.0/config_entries_index.md b/website/versioned_docs/version-0.82.0/config_entries_index.md deleted file mode 100644 index b5b437ad..00000000 --- a/website/versioned_docs/version-0.82.0/config_entries_index.md +++ /dev/null @@ -1,39 +0,0 @@ ---- -title: Config Entries -sidebar_label: Introduction -id: version-0.82.0-config_entries_index -original_id: config_entries_index ---- - -Config Entries are configuration data that are persistently stored by Home Assistant. A config entry is created by a user via the UI. The UI flow is powered by a [config flow handler](config_entries_config_flow_handler.md) as defined by the component. - -## Setting up an entry - -During startup, Home Assistant first calls the [normal component setup](https://developers.home-assistant.io/docs/en/creating_component_index.html), -and then call the method `async_setup_entry(hass, entry)` for each entry. If a new Config Entry is -created at runtime, Home Assistant will also call `async_setup_entry(hass, entry)` ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L119)). - -#### For platforms - -If a component includes platforms, it will need to forward the Config Entry to the platform. This can -be done by calling the forward function on the config entry manager ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/bridge.py#L81)): - -```python -# Use `hass.async_add_job` to avoid a circular dependency between the platform and the component -hass.async_add_job(hass.config_entries.async_forward_entry_setup(config_entry, 'light')) -``` - -For a platform to support config entries, it will need to add a setup entry method ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/light/hue.py#L60)): - -```python -async def async_setup_entry(hass, config_entry, async_add_devices): -``` - -## Unloading entries - -Components can optionally support unloading a config entry. When unloading an entry, the component needs -to clean up all entities, unsubscribe any event listener and close all connections. To implement this, -add `async_unload_entry(hass, entry)` to your component ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L136)). - -Platforms will not need to add any logic for unloading a config entry. The entity component will take care of this. -If you need to clean up resources used for an entity, implement the `async_will_remove_from_hass` method on the Entity ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/media_player/cast.py#L313)). diff --git a/website/versioned_docs/version-0.82.0/creating_component_code_review.md b/website/versioned_docs/version-0.82.0/creating_component_code_review.md deleted file mode 100644 index 0b70b439..00000000 --- a/website/versioned_docs/version-0.82.0/creating_component_code_review.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Checklist for creating a component -id: version-0.82.0-creating_component_code_review -original_id: creating_component_code_review ---- - -A checklist of things to do when you're adding a new component. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on components level - -### 1. Requirements - - 1. Requirement version pinned: `REQUIREMENTS = ['phue==0.8.1']` - 2. We no longer want requirements hosted on GitHub. Please upload to PyPi. - 3. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Configuration - - 1. Voluptuous schema present for [configuration validation](development_validation.md) - 2. Default parameters specified in voluptuous schema, not in `setup(…)` - 3. Schema using as many generic config keys as possible from `homeassistant.const` - 4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`. - 5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation` - 6. Never depend on users adding things to `customize` to configure behavior inside your component. - -### 3. Component/platform communication - - 1. If you need to share global data with platforms, use the dictionary `hass.data`. `hass.data[DATA_XY]` while `XY` is the component is preferred over `hass.data[DOMAIN]`. - 2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`. - - -### 4. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - -```python -# bad -status = requests.get(url('/status')) - -# good -from phue import Bridge -bridge = Bridge(...) -status = bridge.status() -``` - -### 5. Limit platforms included in initial pull request -Large pull requests mean there is a larger chance of finding problems that need to be addressed, and more code that needs to be reviewed between every requested change. If your new component will have multiple platforms, try and limit your initial pull request to a single platform. Once the initial component is merged, you can submit additional PRs for the remaining platforms. This allows reviewers to sign off on smaller chunks of code one at a time, and lets us get your new feature in sooner. Pull requests containing large code dumps will not be a priority for review. diff --git a/website/versioned_docs/version-0.82.0/creating_component_deps_and_reqs.md b/website/versioned_docs/version-0.82.0/creating_component_deps_and_reqs.md deleted file mode 100644 index 41ae8a32..00000000 --- a/website/versioned_docs/version-0.82.0/creating_component_deps_and_reqs.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Requirements & Dependencies -id: version-0.82.0-creating_component_deps_and_reqs -original_id: creating_component_deps_and_reqs ---- - -Home Assistant allows components and platforms to specify their dependencies and requirements using the variables `DEPENDENCIES` and `REQUIREMENTS`. Both are lists that contain strings. - -## Dependencies - -Dependencies are other Home Assistant components that should be setup before the platform is loaded. An example is the MQTT sensor component, which requires an active connection to an MQTT broker. If Home Assistant is unable to load and setup the MQTT component, it will not setup the MQTT sensor component. - -```python -DEPENDENCIES = ['mqtt'] -``` - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you running in a virtual environment. This will make sure that all requirements are present at startup. If steps fails like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is a list of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v0.6.12: - -```python -REQUIREMENTS = ['pychromecast==0.6.12'] -``` - -### Note - -Be aware that actual python imports of these dependencies should be done inside functions that use them. This is because Home Assistant installs requirements on demand and so the requirement won't be loaded the first time your component is loaded. - -Example: - -```python -REQUIREMENTS = ['pychromecast==0.6.12'] - -def setup(hass, config): - import pychromecast - - -``` - -### Custom requirements during development & testing - -During development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using pychromecast as an example: - -* `pip install pychromecast==0.6.13 --target ~/.homeassistant/deps` -* `hass --skip-pip` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is currently in `REQUIREMENTS`. - -If you need to make changes to a requirement to support your component, it's also possible to `pip install` from a checkout of the requirement. - -* `git clone https://github.com/balloob/pychromecast.git` -* `pip install ./pychromecast` -* `hass --skip-pip` - -For testing and development purposes you can also to point to a hosted package in the form of an archive (zip/tar.gz) file as a requirement. GitHub provides archive files for a specific branch, release or even a specific commit. To do that the string in `REQUIREMENTS` needs to be composed of two parts: - -* an URL pointing to the archive file (e.g. `https://github.com/my/repo/archive/branch-x.zip`) -* a hashtag and `pip` string (as described above) to declare what package and version that archive file contains - -Note: Components and platforms included in Home Assistant should point to published PyPI packages. This ensures that the unit tests will not be slowed down as they can be cached. - -For example, the Neato robot vacuum components specifies the v.0.0.5 release on GitHub as a requirement that gets installed as pybotvac version 0.0.5 (`pybotvac==0.0.5`). - -```python -REQUIREMENTS = ['https://github.com/jabesq/pybotvac/archive/v0.0.5.zip#pybotvac==0.0.5'] -``` diff --git a/website/versioned_docs/version-0.82.0/creating_component_generic_discovery.md b/website/versioned_docs/version-0.82.0/creating_component_generic_discovery.md deleted file mode 100644 index 7ebd927e..00000000 --- a/website/versioned_docs/version-0.82.0/creating_component_generic_discovery.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Generic Platform Discovery -id: version-0.82.0-creating_component_generic_discovery -original_id: creating_component_generic_discovery ---- - -New controller or hub components often need to add platforms in sub-components (i.e. Lights & Switches) without additional configuration. -This can be achieved using the `load_platform` or `async_load_platform` methods from `homeassistant.helpers.discovery`: - -```python -def load_platform(hass, component, platform, discovered, hass_config) -``` - -From more info on how this works, refer to the [load_platform](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/discovery.py#L117) method. - -### Example - -Say you need to implement your new MyFlashyHub that controls both Switches & Lights, you can follow these steps: - -Configuration required for your new hub component: - -```yaml -myflashyhub: - example: setting -``` - -The source for your component can be located in your configuration directory for now: - -```bash -~/.homeassistant/custom_components/myflashyhub.py -~/.homeassistant/custom_components/light/myflashyhub.py -~/.homeassistant/custom_components/switch/myflashyhub.py -``` - -In the hub component `myflashyhub.py` you can call your light and switch components. To pass any non-serializable information to the platforms in the sub-component, you should use `hass.data`. - -```python -from homeassistant.helpers.discovery import load_platform - -DOMAIN = 'myflashyhub' -DATA_MFH = 'MFH' - -def setup(hass, hass_config): - """Your controller/hub specific code.""" - hass.data[DATA_MFH] = SomeObjectToInitialise() - - #--- snip --- - load_platform(hass, 'light', DOMAIN, None, hass_config) - load_platform(hass, 'switch', DOMAIN, {'optional': 'arguments'}, hass_config) -``` - -Add your custom device specific code to the `setup_platform` method in `light/myflashyhub.py` and `switch/myflashyhub.py`. - -```python -import custom_components.myflashyhub as myflashyhub - -# 'switch' will receive discovery_info={'optional': 'arguments'} -# as passed in above. 'light' will receive discovery_info=None -def setup_platform(hass, config, add_devices, discovery_info=None): - """Your switch/light specific code.""" - # You can now use hass.data[myflashyhub.DATA_MFH] -``` - - -The `load_platform` method allows the platforms to be loaded without the need for any additional platform entries in your `configuration.yaml` file, which normally would have been: - -```yaml -#light: -# platform: myflashyhub -#switch: -# platform: myflashyhub -``` diff --git a/website/versioned_docs/version-0.82.0/development_checklist.md b/website/versioned_docs/version-0.82.0/development_checklist.md deleted file mode 100644 index 239e12aa..00000000 --- a/website/versioned_docs/version-0.82.0/development_checklist.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Development Checklist -id: version-0.82.0-development_checklist -original_id: development_checklist ---- - - -Before you commit any changes, check your work against these requirements: - -- All communication to external devices or services must be wrapped in an external Python library hosted on [pypi](https://pypi.python.org/pypi). -- All dependencies from [pypi](https://pypi.python.org/pypi) are included via the `REQUIREMENTS` variable in your platform or component and only imported inside functions that use them -- New dependencies are added to `requirements_all.txt` (if applicable), using `script/gen_requirements_all.py` -- The `.coveragerc` file is updated to exclude your platform if there are no tests available or your new code uses a third-party library for communication with the device, service, or sensor -- Documentation is developed for [home-assistant.io](/) - * It's OK to start with adding a docstring with configuration details (for example, sample entry for `configuration.yaml` file) to the file header. Visit the [website documentation](https://www.home-assistant.io/developers/documentation/) for more information about contributing to [home-assistant.io](https://github.com/home-assistant/home-assistant.github.io). diff --git a/website/versioned_docs/version-0.82.0/development_guidelines.md b/website/versioned_docs/version-0.82.0/development_guidelines.md deleted file mode 100644 index abbcf3a1..00000000 --- a/website/versioned_docs/version-0.82.0/development_guidelines.md +++ /dev/null @@ -1,100 +0,0 @@ ---- -title: Style guidelines -id: version-0.82.0-development_guidelines -original_id: development_guidelines ---- - -Home Assistant enforces strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. We automatically test every pull request as part of the linting process with [Coveralls](https://coveralls.io/github/home-assistant/home-assistant) and [Travis CI](https://travis-ci.org/home-assistant/home-assistant). - -Summary of the most relevant points: - -- Line length is limited to 79 characters (see below). -- Use 4 spaces per indentation level. We don't use tabs. -- Comments should be full sentences and end with a period. -- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered. -- Constants and the content of lists and dictionaries should be in alphabetical order. -- Avoid trailing whitespace but surround binary operators with a single space. -- Line separator should be set to `LF`. - -The maximum line length comes directly from the [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/#maximum-line-length), and is also used by the Python standard library. All code must pass these linting checks, and no exceptions will be made. There have already been numerous requests to increase the maximum line length, but after evaluating the options, the Home Assistant maintainers have decided to stay at 79 characters. This decision is final. - -Those points may require that you adjust your IDE or editor settings. - -## Our recommendations - -For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code unified. - -### Quotes - -Use single quotes `'` for single word and `"` for multiple words or sentences. - -```python -ATTR_WATERLEVEL = 'level' -CONF_ATTRIBUTION = "Data provided by the WUnderground weather service" -SENSOR_TYPES = { - 'alerts': ['Alerts', None], -} -``` - -### File headers - -The docstring in the file header should contain a link to the documentation to make it easy to find further information, especially about the configuration or details which are not mentioned in the code. - -```python -""" -Support for MQTT lights. - -For more details about this platform, please refer to the documentation at -https://home-assistant.io/components/light.mqtt/ -""" -``` - -### Requirements - -Please place [Platform requirements](creating_platform_code_review.md#1-requirements) right after the imports. - -```python -[...] -from homeassistant.helpers.entity import Entity - -REQUIREMENTS = ['xmltodict==0.11.0'] -``` - -### Log messages - -There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. Try to avoid brackets and additional quotes around the output to make it easier for users to parse the log. A widely style is shown below but you are free to compose the messages as you like. - -```python -_LOGGER.error("No route to device: %s", self._resource) -``` - -```bash -2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18 -``` - -Don't print out wrong API keys, tokens, usernames, or passwords. -Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` in anything else. - -### Ordering of imports - -Instead of order the imports manually, use [`isort`](https://github.com/timothycrosley/isort). - -```bash -$ pip3 install isort -$ isort homeassistant/components/sensor/fixer.py -``` - -### Use new style string formatting - -Prefer [new style string formatting](https://www.python.org/dev/peps/pep-3101/) over old. - -```python -"{} {}".format('New', 'style') -"%s %s" % ('Old', 'style') -``` - -Except when doing logging here the format is: - -```python -_LOGGER.info("Can't connect to the webservice %s at %s", string1, string2) -``` diff --git a/website/versioned_docs/version-0.82.0/development_validation.md b/website/versioned_docs/version-0.82.0/development_validation.md deleted file mode 100644 index 5611aacc..00000000 --- a/website/versioned_docs/version-0.82.0/development_validation.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: Validate the input -id: version-0.82.0-development_validation -original_id: development_validation ---- - -The `configuration.yaml` file contains the configuration options for components and platforms. We use [voluptuous](https://pypi.python.org/pypi/voluptuous) to make sure that the configuration provided by the user is valid. Some entries are optional or could be required to set up a platform or a component. Others must be a defined type or from an already-defined list. - -We test the configuration to ensure that users have a great experience and minimize notifications if something is wrong with a platform or component setup before Home Assistant runs. - -Besides [voluptuous](https://pypi.python.org/pypi/voluptuous) default types, many custom types are available. For an overview, take a look at the [config_validation.py](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/config_validation.py) helper. - -- Types: `string`, `byte`, and `boolean` -- Entity ID: `entity_id` and `entity_ids` -- Numbers: `small_float` and `positive_int` -- Time: `time`, `time_zone` -- Misc: `template`, `slug`, `temperature_unit`, `latitude`, `longitude`, `isfile`, `sun_event`, `ensure_list`, `port`, `url`, and `icon` - -To validate platforms using [MQTT](https://www.home-assistant.io/components/mqtt/), `valid_subscribe_topic` and `valid_publish_topic` are available. - -Some things to keep in mind: - -- Use the constants defined in `const.py` -- Import `PLATFORM_SCHEMA` from the parent component and extend it -- Preferred order is `required` first and `optional` second -- Starting with Home Assistant 0.64 `voluptuous` requires default values for optional configuration keys to be valid values. Don't use a default which is `None` like `vol.Optional(CONF_SOMETHING, default=None): cv.string`, set the default to `default=''` if required. - -### Snippets - -This section contains snippets for the validation we use. - -#### Default name - -It's common to set a default for a sensor if the user doesn't provide a name to use. - -```python -DEFAULT_NAME = 'Sensor name' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, -``` - -#### Limit the values - -You might want to limit the user's input to a couple of options. - -```python -DEFAULT_METHOD = 'GET' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): vol.In(['POST', 'GET']), -``` - -#### Port - -All port numbers are from a range of 1 to 65535. - -```python -DEFAULT_PORT = 993 - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, -``` - -#### Lists - -If a sensor has a pre-defined list of available options, test to make sure the configuration entry matches the list. - -```python -SENSOR_TYPES = { - 'article_cache': ('Article Cache', 'MB'), - 'average_download_rate': ('Average Speed', 'MB/s'), -} - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_MONITORED_VARIABLES, default=[]): - vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), -``` diff --git a/website/versioned_docs/version-0.82.0/documentation_index.md b/website/versioned_docs/version-0.82.0/documentation_index.md deleted file mode 100644 index 6a6de4f8..00000000 --- a/website/versioned_docs/version-0.82.0/documentation_index.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Documentation -id: version-0.82.0-documentation_index -original_id: documentation_index ---- - -The user documentation is located at [https://www.home-assistant.io](https://www.home-assistant.io). This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. You work on your change and propose it via a Pull Request (PR). - -Once you've created a Pull Request (PR), you can see a preview of the proposed changes by clicking *Details* against Netlify checker in the checkers section of the PR as soon as deployment is complete. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process of working on the website is no different from working on Home Assistant itself. - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.3.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` (You might have to run this command as `sudo`). -- Fork the home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.io). -- In your home-assistant.io root directory, run `$ bundle` to install the gems you need. - -Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` -Shortcut for Debian/Ubuntu: `$ sudo apt-get install ruby ruby-dev ruby-bundler ruby-json && bundle` - -Then you can work on the documentation: - -- Run `bundle exec rake generate` to generate the every first preview. This will take a couple of minutes. -- Create/edit/update a page. The components/platforms documentation is located in `source/_components/`. `source/_docs/` contains the Home Assistant documentation itself. -- Test your changes to home-assistant.io locally: run `bundle exec rake preview` and navigate to [http://127.0.0.1:4000](http://127.0.0.1:4000). While this command is working, any changes to a file are automatically detected and will update the affected pages. You will have to manually reload them in the browser though. -- Create a Pull Request (PR) against the **next** branch of home-assistant.io if your documentation is a new feature, platform, or component. -- Create a Pull Request (PR) against the **current** branch of home-assistant.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -The site generated by `bundle exec rake` is only available locally. If you are developing on a headless machine, use port forwarding: - -```bash -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` - -## Speeding up site generation - -Every release we post long changelogs to the website. This slows down generation of the website significantly! We include some tools to temporarily exclude components and blog posts that you're not working on out of the way. - -```bash -bundle exec rake isolate[filename-of-blogpost-or-component] -``` - -When you're done working on the site, run the following command to move the pages back again: - -```bash -bundle exec rake integrate -``` diff --git a/website/versioned_docs/version-0.82.0/entity_registry_index.md b/website/versioned_docs/version-0.82.0/entity_registry_index.md deleted file mode 100644 index e16a32d3..00000000 --- a/website/versioned_docs/version-0.82.0/entity_registry_index.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Entity Registry -sidebar_label: Introduction -id: version-0.82.0-entity_registry_index -original_id: entity_registry_index ---- - -The entity registry is a registry where Home Assistant keeps track of entities. Any entity that is added to Home Assistant and has a unique ID will be registered in the registry. - -Being registered has the advantage that the same entity will always get the same entity ID. It will also prevent other entities from using that entity ID. - -A user is also able to override the name of an entity in the entity registry. When set, the name of the entity registry is used in favor of the name the device might give itself. - -## Unique ID requirements - -An entity is looked up in the registry based on a combination of domain (ie `light`), platform name (ie `hue`) and the unique ID of the entity. It is therefore very important that the unique ID is unique! It is also important that it is not possible for the user to change the unique ID, because that means it will lose all its settings related to it. - -Good sources for a unique ID: - - - Serial number of a device - - MAC address of a device - - latitude/longitude - -If a device has a single serial but provides multiple entities, combine the serial with unique identifiers for the entities. For example, if a device measures both temperature and humidity, you can uniquely identify the entities using `{serial}-{sensor_type}`. diff --git a/website/versioned_docs/version-0.82.0/entity_sensor.md b/website/versioned_docs/version-0.82.0/entity_sensor.md deleted file mode 100644 index d294f390..00000000 --- a/website/versioned_docs/version-0.82.0/entity_sensor.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Sensor Entity -sidebar_label: Sensor -id: version-0.82.0-entity_sensor -original_id: entity_sensor ---- - -A sensor is a read-only entity that provides some information. Information has a value and optionally, a unit of measurement. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| state | string | **Required** | The value of the sensor. -| unit_of_measurement | string | `None` | The unit of measurement that the sensor is expressed in. -| device_class | string | `None` | Type of sensor. - -### Available device classes - -If specifying a device class, your sensor entity will need to also return the correct unit of measurement. - -| Type | Unit | Description -| ---- | ---- | ----------- -| battery | % | % of battery that is left. -| humidity | % | % of humidity in the air. -| illuminance | lx/lm | Light level. -| temperature | C/F | Temperature. -| timestamp | ISO8601 | Timestamp -| pressure | hPa,mbar | Pressure. diff --git a/website/versioned_docs/version-0.82.0/hassio_addon_config.md b/website/versioned_docs/version-0.82.0/hassio_addon_config.md deleted file mode 100644 index de4a40a2..00000000 --- a/website/versioned_docs/version-0.82.0/hassio_addon_config.md +++ /dev/null @@ -1,210 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.82.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use `jq` inside your shell script to parse this data. However, you might have to install `jq` as a separate package in your container (see `Dockerfile` below). - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -## Add-on Docker file - -All add-ons are based on Alpine Linux 3.6. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | no | List of supported arch: `armhf`, `aarch64`, `amd64`, `i386`. Default all. -| machine | list | no | Default it support any machine type. You can select that this add-on run only on specific machines. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`, `DAC_READ_SEARCH`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| auth_api | bool | no | Allow access to Home Assistent user backend. - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. diff --git a/website/versioned_docs/version-0.82.0/hassio_addon_index.md b/website/versioned_docs/version-0.82.0/hassio_addon_index.md deleted file mode 100644 index 9e820b97..00000000 --- a/website/versioned_docs/version-0.82.0/hassio_addon_index.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -title: Developing an add-on -sidebar_label: Introduction -id: version-0.82.0-hassio_addon_index -original_id: hassio_addon_index ---- - -Add-ons for Hass.io allow the user to extend the functionality around Home Assistant. This can be running an application that Home Assistant can integrate with (like an MQTT broker) or to share the configuration via Samba for easy editing from other computers. Add-ons can be configured via the Hass.io panel in Home Assistant. - -Under the hood, add-ons are Docker images published in [Docker Hub](https://hub.docker.com/). Developers can create [GitHub](https://github.com) repositories that contain multiple references to add-ons for easy sharing with the community. - -1. [Tutorial: Making your first add-on](hassio_addon_tutorial.md) -1. [Configuration](hassio_addon_config.md) -1. [Communication](hassio_addon_communication.md) -1. [Local Testing](hassio_addon_testing.md) -1. [Publishing](hassio_addon_publishing.md) -1. [Presentation](hassio_addon_presentation.md) -1. [Repositories](hassio_addon_repository.md) -1. [Security](hassio_addon_security.md) diff --git a/website/versioned_docs/version-0.83.0/app_integration_index.md b/website/versioned_docs/version-0.83.0/app_integration_index.md deleted file mode 100644 index d848d4d9..00000000 --- a/website/versioned_docs/version-0.83.0/app_integration_index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Native App Integration -sidebar_label: Introduction -id: version-0.83.0-app_integration_index -original_id: app_integration_index ---- - -This guide describes how to build a native Home Assistant app that communicates with Home Assistant and offers a seamless integration. Below is a list of the things that we will discuss in this guide. - -- Allow the user to establish a connection and authenticate with their own Home Assistant instance. -- Send location and device info back to Home Assistant. -- A view to control the house via an authenticated webview. diff --git a/website/versioned_docs/version-0.83.0/app_integration_sending_data.md b/website/versioned_docs/version-0.83.0/app_integration_sending_data.md deleted file mode 100644 index 291136cb..00000000 --- a/website/versioned_docs/version-0.83.0/app_integration_sending_data.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Sending data home -id: version-0.83.0-app_integration_sending_data -original_id: app_integration_sending_data ---- - -There are different APIs that your app can use to send data back or communicate with Home Assistant. - -## Short note on instance URLs - -Some users have configured Home Assistant to be available outside of their home network using a dynamic DNS service. There are some routers that don't support hairpinning / NAT loopback: a device sending data from inside the routers network, via the externally configured DNS service, to Home Asisstant, which also resides inside the local network. - -To work around this, the app will need to record which WiFi is the home network, and use a direct connection when connected to the home WiFi network. - -## Webhooks - -Any component in Home Assistant can register webhook endpoints. The webhook endpoints contain a randomized URL-segment which are bound to just a single update handler. Because of this, the call requires no authentication, making calls have little overhead. - -Webhooks are ideal for sending quick updates, like location or battery, from your app to Home Assistant. - -Webhooks are available on the local instance on `/api/webhook/`, which requires a direct connection. If the Home Assistant instance is configured to use Home Assistant Cloud, it is possible to get a cloud url for the webhook. This url is accessible from anywhere on the internet. - -To register a webhook in your component: - -```python -async def handle_webhook(hass, webhook_id, request): - """Handle webhook callback.""" - body = await request.json() - # Do something with the data - - -webhook_id = hass.components.webhook.async_generate_id() - -hass.components.webhook.async_register( - DOMAIN, 'Name of the webhook', webhook_id, handle_webhook) - -print( - "Webhook available on:", - hass.components.webhook.async_generate_url(webhook_id) -) -``` - -## Websocket API - -With a websocket connection you will be able to stream updates from Home Assistant and control most of the things inside Home Assistant. This API is perfect if you want to show a realtime view of the house and allow the user to interact with it. - -Websocket API requires authentication via an access token and a direct connection with the instance. - -- [Websocket API Docs](external_api_websocket) -- [Making authenticated requests](auth_api#making-authenticated-requests) - -## Rest API - -With the Rest API you are able to query the state of the house and call services. Your component is also able to register new HTTP views to offer other Rest API endpoints. - -Rest API requires authentication via an access token and a direct connection with the instance. - -- [Rest API Docs](external_api_rest) -- [Making authenticated requests](auth_api#making-authenticated-requests) diff --git a/website/versioned_docs/version-0.83.0/app_integration_setup.md b/website/versioned_docs/version-0.83.0/app_integration_setup.md deleted file mode 100644 index 935d24b5..00000000 --- a/website/versioned_docs/version-0.83.0/app_integration_setup.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Connecting to an instance -id: version-0.83.0-app_integration_setup -original_id: app_integration_setup ---- - -When a user first opens the app, they will need to connect to their local instance to authenticate and register the device. - -## Authenticating the user - -The local instance can be discovered if Home Assistant has the [zeroconf component] configured. If not configured, the user will need to be asked for the local address of their instance. - -When the address of the instance is known, the app will ask the user to authenticate via [OAuth2 with Home Assistant]. Home Assistant uses IndieAuth, which means that to be able to redirect to a url that triggers your app, you need to take some extra steps. Make sure to read the last paragraph of the "Clients" section thoroughly. - -## Registering the device - -Once you have tokens to authenticate as a user, it's time to register the app with the app component in Home Assistant. Each native app will need to build their own support layer for their app. The setup of your component will need to use a config flow so that it is configurable via the user interface and can access advanced Home Assistant features like the device registry. - -Let's take as an example that we're building an iOS application and that it is supported by the `ios` component in Home Assistant. If the component is loaded, it will register a new API endpoint on `/api/ios/register` (requiring authentication). The app can post to this endpoint to register the users' device with Home Assistant. Example payload: - -```json -{ - "device_type": "iPhone 6", - "firmware": "zxcx" -} -``` - -The endpoint will register the device with Home Assistant: - - - Generate a unique webhook endpoint that the app can use to send data back to Home Assistant. - - Use the storage helper to store data. - - Register the iOS device with the [device registry](device_registry_index). - - Make the device available as a notification target. - -> The following section is not implemented yet. - -If the app receives a 404 HTTP status code when trying to register the device, it means the `ios` component is not loaded. In this case, the app can load the `ios` component by posting to `/api/config_entry_discovery`. This will trigger the `http_discovery` step of the config flow for the `ios` component and it will be loaded. The app can now retry the device registration. - -[zeroconf component]: https://www.home-assistant.io/components/zeroconf -[OAuth2 with Home Assistant]: auth_api diff --git a/website/versioned_docs/version-0.83.0/app_integration_webview.md b/website/versioned_docs/version-0.83.0/app_integration_webview.md deleted file mode 100644 index 69658909..00000000 --- a/website/versioned_docs/version-0.83.0/app_integration_webview.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Authenticated Webview -id: version-0.83.0-app_integration_webview -original_id: app_integration_webview ---- - -Your application already asked the user to authenticate. This means that your app should not ask the user to authenticate again when they open the Home Assistant UI. - -To make this possible, the Home Assistant UI supports [external authentication](frontend_external_auth). This allows your app to provide hooks so that the frontend will ask your app for access tokens. - -Note that this feature requires a direct connection to the instance. diff --git a/website/versioned_docs/version-0.83.0/auth_api.md b/website/versioned_docs/version-0.83.0/auth_api.md deleted file mode 100644 index 1d1c1b5b..00000000 --- a/website/versioned_docs/version-0.83.0/auth_api.md +++ /dev/null @@ -1,257 +0,0 @@ ---- -title: Authentication API -sidebar_label: API -id: version-0.83.0-auth_api -original_id: auth_api ---- - -This page will describe the steps required for your application to authorize against and integrate with Home Assistant instances. [See a demo](https://hass-auth-demo.glitch.me) powered by our helper lib [home-assistant-js-websocket](https://github.com/home-assistant/home-assistant-js-websocket). - -Each user has their own instance of Home Assistant which gives each user control over their own data. However, we also wanted to make it easy for third party developers to create applications that allow users to integrate with Home Assistant. To achieve this, we have adopted the [OAuth 2 specification][oauth2-spec] combined with the [OAuth 2 IndieAuth extension][indieauth-spec] for generating clients. - -## Clients - -Before you can ask the user to authorize their instance with your application, you will need a client. In traditional OAuth2, the server needs to generate a client before a user can authorize. However, as each server belongs to a user, we've adopted a slightly different approach from [IndieAuth][indieauth-clients]. - -The client ID you need to use is the website of your application. The redirect url has to be of the same host and port as the client ID. For example: - - - client id: `https://www.my-application.io` - - redirect uri: `https://www.my-application.io/hass/auth_callback` - -If you require a different redirect url (ie, if building a native app), you can add an HTML tag to the content of the website of your application (the client ID) with an approved redirect url. For example, add this to your site to whitelist redirect uri `hass://auth`: - -```html - -``` - -Home Assistant will scan the first 10kB of a website for link tags. - -## Authorize - -[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd) - -> All example URLs here are shown with extra spaces and new lines for display purposes only. - -The authorize url should contain `client_id` and `redirect_uri` as query parameters. - -``` -http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2F%3Fauth_callback%3D1 -``` - -Optionally you can also include a `state` parameter, this will be added to the redirect uri. The state is perfect to store the instance url that you are authenticating with. Example: - -``` -http://your-instance.com/auth/authorize? - client_id=https%3A%2F%2Fhass-auth-demo.glitch.me& - redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2Fauth_callback& - state=http%3A%2F%2Fhassio.local%3A8123 -``` - -The user will navigate to this link and be presented with instructions to log in and authorize your application. Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code and state as part of the query parameters. Example: - -``` -https://hass-auth-demo.glitch.me/auth_callback - code=12345& - state=http%3A%2F%2Fhassio.local%3A8123 -``` - -This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section). - -## Token - -The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. In thee case of refresh token, the token endpoint is also capable of revoking a token. - -All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`. - -### Authorization code - -> All requests to the token endpoint need to contain the exact same client ID as was used to redirect the user to the authorize endpoint. - -Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is: - -``` -grant_type=authorization_code& -code=12345& -client_id=https%3A%2F%2Fhass-auth-demo.glitch.me -``` - -The return response will be an access and refresh token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "refresh_token": "IJKLMNOPQRST", - "token_type": "Bearer" -} -``` - -The access token is a short lived token that can be used to access the API. The refresh token can be used to fetch new access tokens. The `expires_in` value is seconds that the access token is valid. - -An HTTP status code of 400 will be returned if an invalid request has been issued. The HTTP status code will be 403 if a token is requested for an inactive user. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Refresh token - -Once you have retrieved a refresh token via the grant type `authorization_code`, you can use it to fetch new access tokens. The request body is: - -``` -grant_type=refresh_token& -refresh_token=IJKLMNOPQRST& -client_id=https%3A%2F%2Fhass-auth-demo.glitch.me -``` - -The return response will be an access token: - -```json -{ - "access_token": "ABCDEFGH", - "expires_in": 1800, - "token_type": "Bearer" -} -``` - -An HTTP status code of 400 will be returned if an invalid request has been issued. - -```json -{ - "error": "invalid_request", - "error_description": "Invalid client id", -} -``` - -### Revoking a refresh token - -> client_id is not need for revoke refresh token - -The token endpoint is also capable of revoking a refresh token. Revoking a refresh token will immediately revoke the refresh token and all access tokens that it has ever granted. To revoke a refresh token, make the following request: - -``` -token=IJKLMNOPQRST& -action=revoke -``` - -The request will always respond with an empty body and HTTP status 200, regardless if the request was successful. - -## Long-lived access token - -A long-lived access token is usually used for 3rd party API calls and webhook-ish integrations. To generate a long-lived access token, an active websocket connection has to be established. - -Send websocket command `auth/long_lived_access_token` will create a long-lived access token for current user. Access token will not be saved in Home Assistant. User need to record the token in secure place. - -```json -{ - "id": 11, - "type": "auth/long_lived_access_token", - "client_name": "GPS Logger", - "client_icon": null, - "lifespan": 365 -} -``` - -Result will be a long-lived access token: - -```json -{ - "id": 11, - "type": "result", - "success": true, - "result": "ABCDEFGH" -} -``` - -Additionally, a long-lived access token can be created using the UI tool located at the bottom of the user's Home Assistant profile page. - -## Making authenticated requests - -Once you have an access token, you can make authenticated requests to the Home Assistant APIs. - -For the websocket connection, pass the access token in the [authentication message](https://developers.home-assistant.io/docs/en/external_api_websocket.html#authentication-phase). - -For HTTP requests, pass the token type and access token as the authorization header: - -``` -Authorization: Bearer ABCDEFGH -``` - -### Example: cURL - -```shell -curl -X GET \ - https://your.awesome.home/api/error/all \ - -H 'Authorization: Bearer ABCDEFGH' -``` - -### Example: Python - -```python -import requests - -url = "https://your.awesome.home/api/error/all" -headers = { - 'Authorization': "Bearer ABCDEFGH", -} -response = requests.request('GET', url, headers=headers) - -print(response.text) -``` - -### Example: NodeJS -```JavaScript -fetch('https://your.awesome.home/api/error/all', { - headers: { Authorization: 'Bearer ABCDEFGH' } -}).then(function (response) { - if (!response.ok) { - return Promise.reject(response); - } - return response.text(); -}).then(function (body ) { - console.log(body); -}); -``` - -If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and so the user is no longer logged in. You should clear the user's data and ask the user to authorize again. - -[oauth2-spec]: https://tools.ietf.org/html/rfc6749 -[indieauth-spec]: https://indieauth.spec.indieweb.org/ -[indieauth-clients]: https://indieauth.spec.indieweb.org/#client-identifier - -## Signed paths - -Sometimes you want a user to make a GET request to Home Assistant to download data. In this case the normal auth system won't do, as we can't link the user to an API with the auth header attached to it. In that case, a signed path can help. - -A signed path is a normal path on our server, like `/api/states`, but with an attached secure authentication signature. The user is able to navigate to this path and will be authorised as the access token that created the signed path. Signed paths can be created via the websocket connection and are meant to be shortlived. The default expiration is 30 seconds. - -To get a signed path, send the following command: - -```js -{ - "type": "auth/sign_path", - "path": "/api/states", - // optional, expiration time in seconds. Defaults to 30 seconds - "expires": 20 -} -``` - -The response will contain the signed path: - -```js -{ - "path": "/api/states?authSig=ABCDEFGH" -} -``` - -Some things to note about a signed path: - - - If the refresh token is deleted, the signed url is no longer valid. - - If the user is deleted, the signed url is no longer valid (because the refresh token will be deleted). - - If Home Assistant is restarted, the signed url is no longer valid. - - Access is only validated when the request is received. If a response takes longer than the expiration time (ie, downloading a large file), the download will continue after the expiration date has passed. diff --git a/website/versioned_docs/version-0.83.0/external_api_server_sent_events.md b/website/versioned_docs/version-0.83.0/external_api_server_sent_events.md deleted file mode 100644 index 63c47259..00000000 --- a/website/versioned_docs/version-0.83.0/external_api_server_sent_events.md +++ /dev/null @@ -1,74 +0,0 @@ ---- -title: Server-sent events -id: version-0.83.0-external_api_server_sent_events -original_id: external_api_server_sent_events ---- - -The [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) feature is a one-way channel from your Home Assistant server to a client which is acting as a consumer. For a bi-directional streaming API, check out the [WebSocket API](external_api_websocket.md). - -The URI that is generating the data is `/api/stream`. - -A requirement on the client-side is existing support for the [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) interface. - -There are various ways to access the stream. If you have not set an `api_password` in the [`http`](https://www.home-assistant.io/components/http/) section of your `configuration.yaml` file then you use your modern browser to read the messages. A command-line option is `curl`: - -```bash -$ curl -X GET -H 'Authorization: Bearer ABCDEFGH' \ - -H "Content-Type: application/json" http://localhost:8123/api/stream -``` - -> Will no longer work with the new Authentication system. - -You can create a convenient view for this by creating an HTML file (`sse.html`) in the `www` folder of your Home Assistant configuration directory (`.homeassistant`). Paste this snippet into the file: - -```html - - - -

Getting Home Assistant server events

-
- - - -``` - -Visit [http://localhost:8123/local/sse.html](http://localhost:8123/local/sse.html) to see the stream of events. - -## Examples - -A simple way to consume server-sent events is to use a command-line http client like [httpie](https://httpie.org/). Installation info is on the site (if you use Homebrew, it's `brew install httpie`). Once installed, run this snippet from your terminal: - -```bash -$ http --stream http://localhost:8123/api/stream 'Authorization:Bearer ABCDEFGH' content-type:application/json -``` - -### Website - -> Will no longer work with the new Authentication system. - -The [home-assistant-sse](https://github.com/fabaff/home-assistant-sse) repository contains a more advanced example. - -### Python - -If you want to test the server-sent events without creating a website, the Python module [`sseclient` ](https://pypi.python.org/pypi/sseclient/) can help. To install (assuming Python and pip3 are already installed): - -```bash -$ pip3 install sseclient -``` - -A simple script to consume SSE in Python looks like this: - -```python -from sseclient import SSEClient - -auth = {'Authorization': 'Bearer ABCDEFGH'} -messages = SSEClient('http://localhost:8123/api/stream', headers=auth) - -for msg in messages: - print(msg) -``` diff --git a/website/versioned_docs/version-0.83.0/hassio_addon_presentation.md b/website/versioned_docs/version-0.83.0/hassio_addon_presentation.md deleted file mode 100644 index d6cf84c0..00000000 --- a/website/versioned_docs/version-0.83.0/hassio_addon_presentation.md +++ /dev/null @@ -1,48 +0,0 @@ ---- -title: Presenting your add-on -id: version-0.83.0-hassio_addon_presentation -original_id: hassio_addon_presentation ---- - -If you decide to share your add-on to the public, paying attention to details is recommended. Of course, your add-on should have a proper name and description, but Hass.io also gives you some other tools to present your add-on even nicer. - -## Adding documentation - -Good documentation helps the consumer of your add-on to understand its usage, explains configuration options, points users in the right direction in the case they have questions or issues, and contains the license under which the add-on was published. - -This file containing the documentation is usually referred to as the "README", which is generally published as the `README.md` file. - -Take a look at other projects for inspiration. For example, see the `README.md` of the [Community Hass.io Add-ons: Homebridge](https://github.com/hassio-addons/addon-homebridge/blob/master/README.md) add-on. - -In future versions of Hass.io, the `README.md` file will be displayed in the Home Assistant frontend. - -## Add-on icon & logo - -A picture is worth a thousand words. Therefore, your add-on can be improved by adding a proper image icon and logo. Those images are used when showing your add-on in the Home Assistant Hass.io panel and which will significantly improve the visual representation of your add-on. - -Requirements for the logo of your add-on: - -- The logo must be in the Portable Network Graphics format (`.png`). -- The filename must be `logo.png`. -- It is recommended to keep the logo size around 250x100px. You may choose to use a different size or aspect ratio as you seem fit for your add-on. - -Requirements for the icon of your add-on: - -- The icon must be in the Portable Network Graphics format (`.png`). -- The filename must be `icon.png`. -- The aspect ratio of the icon must be 1x1 (square). -- It is recommended to use an icon size of 128x128px. - -## Keeping a changelog - -It is likely you are going to release newer versions of your add-on in the future. In case that happens, the users of your add-on would see an upgrade notice and probably want to know what changes were made in the latest version. - -A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of your add-on and is generally published as the `CHANGELOG.md` file. - -If you are in need of a guide on keeping a changelog, we would recommend checking the [keep a changelog](http://keepachangelog.com) website. They have developed a standard that is used by many opensource projects around the world. - -In future versions of Hass.io, the `CHANGELOG.md` file will be displayed in the Home Assistant frontend. - -## AppArmor - -You can use own security profile for you Add-on with AppArmor. Default it is enabled and use the Docker default profile. Put `apparmor.txt` file into your Add-on folder and it will load this file as primary profile. Use the config options to set the name of that profile. diff --git a/website/versioned_docs/version-0.83.0/hassio_addon_publishing.md b/website/versioned_docs/version-0.83.0/hassio_addon_publishing.md deleted file mode 100644 index 9d096f54..00000000 --- a/website/versioned_docs/version-0.83.0/hassio_addon_publishing.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Publishing your add-on -id: version-0.83.0-hassio_addon_publishing -original_id: hassio_addon_publishing ---- - -There are two different ways of publishing add-ons. One is to publish pre-build containers to Docker Hub and the other option is to have users build the containers locally on their Hass.io instance. - -#### Pre-build containers - -With pre-build containers, the developer is responsible for building the images for each architecture on their machine and push the results out to Docker Hub. This has a lot of advantages for the user. As a user it will only have to download the final container and be up and running once the download finishes. This makes the installation process fast and almost no chance of failure. This is the preferred method. - -We have automated the process of building and publishing add-ons. See below for the instructions. - -#### Locally build containers - -Starting Hass.io 0.26, it is possible to distribute add-ons that will be built on the users machine. The advantage is that as a developer it is easy to test an idea and see if people are interested in your add-ons. This method includes installing and potentially compiling code. This means that installing such an add-on is slow and adds more wear and tear to users SD card/hard drive than the above mentioned pre-build solution. It also has a higher chance of failure if one of the dependencies of the container has changed or is no longer available. - -Use this option when you are playing with add-ons and seeing if someone is interested in your work. Once you're an established repository, please migrate to pushing builds to Docker Hub as it greatly improves the user experience. In the future we will mark locally built add-ons in the add-on store to warn users. - -## Build scripts to publish add-ons to Docker Hub - -All add-ons are simple docker containers. Inside your add-on `config.json` you specify the Docker image that will be installed for your add-on: - -```json -{ - ... - "image": "myhub/image-{arch}-addon-name", - ... -} -``` - -You can use `{arch}` inside the image name to support multiple architectures with one (1) configuration file. It will be replaced with the architecture of the user when we load the image. If you use `Buildargs` you can use the `build.json` to overwrite our default args. - -Hass.io assumes that the `master` branch of your add-on repository matches the latest tag on Docker Hub. When you're building a new version, it's suggested that you use another branch, ie `build` or do it with a PR on GitHub. After you push the add-on to [Docker Hub](https://hub.docker.com/), you can merge this branch to master. - -## Custom Add-ons - -You need a Docker Hub account to make your own add-ons. You can build your Docker images with the Docker `build` command or use our script that make it simple. Pull our [Builder Docker engine][builder] and run one of the following commands. - -For a git repository: - -```bash -$ docker run --rm --privileged -v \ - ~/.docker:/root/.docker homeassistant/amd64-builder \ - --all -t addon-folder -r https://github.com/xy/addons \ - -b branchname -``` - -For a local repository: - -```bash -$ docker run --rm --privileged -v \ - ~/.docker:/root/.docker -v /my_addon:/data homeassistant/amd64-builder \ - --all -t /data -``` - -> If you are developing on macOS and using Docker for Mac, you may encounter an error message similar to the following: error creating aufs mount to /var/lib/docker/aufs/mnt/-init: invalid argument. A proposed workaround is to add the following to the Advanced Daemon JSON configuration via Docker > Preferences > Daemon > Advanced: "storage-driver" : "aufs". - -[builder]: https://github.com/home-assistant/hassio-build/tree/master/builder diff --git a/website/versioned_docs/version-0.84.0/creating_component_code_review.md b/website/versioned_docs/version-0.84.0/creating_component_code_review.md deleted file mode 100644 index 01c004b0..00000000 --- a/website/versioned_docs/version-0.84.0/creating_component_code_review.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Checklist for creating a component -id: version-0.84.0-creating_component_code_review -original_id: creating_component_code_review ---- - -A checklist of things to do when you're adding a new component. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on components level - -### 1. Requirements - - 1. Requirement version pinned: `REQUIREMENTS = ['phue==0.8.1']` - 2. We no longer want requirements hosted on GitHub. Please upload to PyPi. - 3. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Configuration - - 1. Voluptuous schema present for [configuration validation](development_validation.md) - 2. Default parameters specified in voluptuous schema, not in `setup(…)` - 3. Schema using as many generic config keys as possible from `homeassistant.const` - 4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`. - 5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation` - 6. Never depend on users adding things to `customize` to configure behavior inside your component. - -### 3. Component/platform communication - - 1. If you need to share global data with platforms, use the dictionary `hass.data`. `hass.data[DATA_XY]` while `XY` is the component is preferred over `hass.data[DOMAIN]`. - 2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`. - - -### 4. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - -```python -# bad -status = requests.get(url('/status')) - -# good -from phue import Bridge -bridge = Bridge(...) -status = bridge.status() -``` - -### 5. Limit platforms included in initial pull request -Large pull requests mean there is a larger chance of finding problems that need to be addressed, and more code that needs to be reviewed between every requested change. If your new component will have multiple platforms, try and limit your initial pull request to a single platform. Once the initial component is merged, you can submit additional PRs for the remaining platforms. This allows reviewers to sign off on smaller chunks of code one at a time, and lets us get your new feature in sooner. Pull requests containing large code dumps will not be a priority for review. - -### 6. Event names -Prefix component event names with component name itself. For example, use `xiaomi_aqara.click` instead of `click` for the `xiaomi_aqara` component. diff --git a/website/versioned_docs/version-0.84.0/external_api_rest.md b/website/versioned_docs/version-0.84.0/external_api_rest.md deleted file mode 100644 index f5e785c9..00000000 --- a/website/versioned_docs/version-0.84.0/external_api_rest.md +++ /dev/null @@ -1,517 +0,0 @@ ---- -title: REST API -id: version-0.84.0-external_api_rest -original_id: external_api_rest ---- - -Home Assistant runs a web server accessible on port 8123. - -* http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -* http://IP_ADDRESS:8123/api/ is a Rest API. - -The API accepts and returns only JSON encoded objects. All API calls have to be accompanied by the header `X-HA-Access: YOUR_PASSWORD` (YOUR_PASSWORD as specified in your `configuration.yaml` file in the [`http:` section](https://www.home-assistant.io/components/http/)). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```bash -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. - -```python -from requests import get - -url = 'http://localhost:8123/ENDPOINT' -headers = { - 'Authorization': 'Bearer ABCDEFGH', - 'content-type': 'application/json', -} - -response = get(url, headers=headers) -print(response.text) -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on a single entity -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates the current state of an entity. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance.
- -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` diff --git a/website/versioned_docs/version-0.85/asyncio_categorizing_functions.md b/website/versioned_docs/version-0.85/asyncio_categorizing_functions.md deleted file mode 100644 index 7828ba33..00000000 --- a/website/versioned_docs/version-0.85/asyncio_categorizing_functions.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Categorizing Functions -id: version-0.85-asyncio_categorizing_functions -original_id: asyncio_categorizing_functions ---- - -A piece of work within Home Assistant is represented by a function that will be invoked. It will either run inside our event loop or inside our thread pool, depending on if it is async safe. - -Home Assistant uses the convention that all functions that must be run from within the event loop are prefixed with `async_`. - -## The coroutine function - -Coroutines are special functions based on Python’s generators syntax which allows them to suspend execution while waiting on a result. - -Invoking a coroutine function will return a Generator object back, but will not actually begin execution. This object will execute the task when it is either yielded from (from within another coroutine) or it is scheduled on the event loop. - -To declare a function a coroutine, import the coroutine annotation from the asyncio package and annotate your function. - -```python -async def async_look_my_coroutine(target): - result = await entity.async_turn_on() - if result: - print("hello {}".format(target)) - -hass.loop.create_task(async_look_my_coroutine("world")) -``` - -In this example, we schedule the coroutine by calling `hass.loop.create_task`. This will add the coroutine to the queue of tasks to be run. When the event loop is running `async_look_my_coroutine` it will suspend the task when `await entity.async_turn_on()` is called. At that point a new task will be scheduled to execute `entity.async_turn_on()`. When that job has been executed, `async_look_my_coroutine` will resume. - -## The callback function - -This is a normal function that is considered safe to be run from within the event loop. A callback is unable to suspend itself and thus cannot do any I/O or call a coroutine. A callback is capable of scheduling a new task but it will not be able to wait for the results. - -To declare a function as a callback, import the callback annotation from the core package and annotate your function. - -A common use case for a callback in Home Assistant is as a listener for an event or a service call. It can process the incoming information and then schedule the right calls to be made. Example from the automation component. - -```python -from homeassistant.core import callback - -@callback -def async_trigger_service_handler(service_call): - """Handle automation trigger service calls.""" - vars = service_call.data.get(ATTR_VARIABLES) - for entity in component.async_extract_from_service(service_call): - hass.loop.create_task(entity.async_trigger(vars, True)) -``` - -In this example, `entity.async_trigger` is a coroutine function. Invoking the coroutine function will return a coroutine task. The passed in parameters will be used when the task gets executed. - -To execute the task we have to schedule it for execution on the event loop. This is done by calling `hass.loop.create_task`. - -### Why even have callbacks? - -You might wonder, if a coroutine can do everything a callback can do, why even have a callback. The reason is performance and better state consistency of the core API objects. - -When coroutine A waits for coroutine B, it will suspend itself and schedule a new task to run B. This means that the event loop is now running A, B and then A again. If B is a callback, A will never have to suspend itself and thus the event loop is just running A. The consistency implication is that other events queued to run on the event loop continue to wait until callbacks complete, but will be interleaved when yielding to another coroutine. - -## Event loop and thread safe - -These are functions that are safe to run both in a thread and inside the event loop. These functions are usually performing a computation or transform data in memory. Anything that does I/O does not fall under this category. Many standard library functions fall in this category. For example generating the sum of a set of numbers using sum or merging two dictionaries. - -There is no special annotation to mark functions as part of this category and care should be taken when using these functions from inside the event loop. When in doubt, look at their implementation. - -## Other functions - -These are all the functions that did not fit in the previous categories. These functions are either thread-safe or not considered safe to be run within the event loop. These are functions that use sleep, or perform I/O. - -There is no special annotation necessary to be considered part of this category. diff --git a/website/versioned_docs/version-0.85/documentation_index.md b/website/versioned_docs/version-0.85/documentation_index.md deleted file mode 100644 index 6df93daa..00000000 --- a/website/versioned_docs/version-0.85/documentation_index.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Documentation -id: version-0.85-documentation_index -original_id: documentation_index ---- - -The user documentation is located at [https://www.home-assistant.io](https://www.home-assistant.io). This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. You work on your change and propose it via a Pull Request (PR). - -Once you've created a Pull Request (PR), you can see a preview of the proposed changes by clicking *Details* against Netlify checker in the checkers section of the PR as soon as deployment is complete. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process of working on the website is no different from working on Home Assistant itself. - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.3.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` (You might have to run this command as `sudo`). -- Fork the home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.io). -- In your home-assistant.io root directory, run `$ bundle` to install the gems you need. - -- Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` -- Shortcut for Debian/Ubuntu: `$ sudo apt-get install ruby ruby-dev ruby-bundler ruby-json g++ zlib1g-dev && bundle` - -Then you can work on the documentation: - -- Run `bundle exec rake generate` to generate the every first preview. This will take a couple of minutes. -- Create/edit/update a page. The components/platforms documentation is located in `source/_components/`. `source/_docs/` contains the Home Assistant documentation itself. -- Test your changes to home-assistant.io locally: run `bundle exec rake preview` and navigate to [http://127.0.0.1:4000](http://127.0.0.1:4000). While this command is working, any changes to a file are automatically detected and will update the affected pages. You will have to manually reload them in the browser though. -- Create a Pull Request (PR) against the **next** branch of home-assistant.io if your documentation is a new feature, platform, or component. -- Create a Pull Request (PR) against the **current** branch of home-assistant.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -The site generated by `bundle exec rake` is only available locally. If you are developing on a headless machine, use port forwarding: - -```bash -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` - -## Speeding up site generation - -Every release we post long changelogs to the website. This slows down generation of the website significantly! We include some tools to temporarily exclude components and blog posts that you're not working on out of the way. - -```bash -bundle exec rake isolate[filename-of-blogpost-or-component] -``` - -When you're done working on the site, run the following command to move the pages back again: - -```bash -bundle exec rake integrate -``` diff --git a/website/versioned_docs/version-0.85/entity_air_pollutants.md b/website/versioned_docs/version-0.85/entity_air_pollutants.md deleted file mode 100644 index 1fd69959..00000000 --- a/website/versioned_docs/version-0.85/entity_air_pollutants.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Air Pollutants Entity -sidebar_label: Air Pollutants -id: version-0.85-entity_air_pollutants -original_id: entity_air_pollutants ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| particulate_matter_2_5 | float | **Required** | The particulate matter 2.5 (<= 2.5 μm) level. -| particulate_matter_10 | float | **Required** | The particulate matter 10 (<= 10 μm) level. -| particulate_matter_0_1 | float | `None` | The particulate matter 0.1 (<= 0.1 μm) level. -| air_quality_index | float | `None` | The Air Quality Index (AQI). -| ozone | float | `None` | The O3 (ozone) level. -| carbon_monoxide | float | `None` | The CO (carbon monoxide) level. -| carbon_dioxide | float | `None` | The CO2 (carbon dioxide) level. -| sulphur_dioxide | float | `None` | The SO2 (sulphur dioxide) level. -| nitrogen_oxide | float | `None` | The N2O (nitrogen oxide) level. -| nitrogen_monoxide | float | `None` | The NO (nitrogen monoxide) level. -| nitrogen_dioxide | float | `None` | The NO2 (nitrogen dioxide) level. -| volatile_organic_compounds | float | `None` | The volatile organic compounds (VOC) level. - -Properties have to follow the units defined in the `unit_system`. - diff --git a/website/versioned_docs/version-0.85/entity_sensor.md b/website/versioned_docs/version-0.85/entity_sensor.md deleted file mode 100644 index 50ab13e2..00000000 --- a/website/versioned_docs/version-0.85/entity_sensor.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Sensor Entity -sidebar_label: Sensor -id: version-0.85-entity_sensor -original_id: entity_sensor ---- - -A sensor is a read-only entity that provides some information. Information has a value and optionally, a unit of measurement. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| state | string | **Required** | The value of the sensor. -| unit_of_measurement | string | `None` | The unit of measurement that the sensor is expressed in. -| device_class | string | `None` | Type of sensor. - -### Available device classes - -If specifying a device class, your sensor entity will need to also return the correct unit of measurement. - -| Type | Unit | Description -| ---- | ---- | ----------- -| battery | % | % of battery that is left. -| humidity | % | % of humidity in the air. -| illuminance | lx/lm | Light level. -| temperature | °C/°F | Temperature. -| timestamp | ISO8601 | Timestamp -| pressure | hPa,mbar | Pressure. diff --git a/website/versioned_docs/version-0.85/external_api_rest.md b/website/versioned_docs/version-0.85/external_api_rest.md deleted file mode 100644 index e6387f56..00000000 --- a/website/versioned_docs/version-0.85/external_api_rest.md +++ /dev/null @@ -1,517 +0,0 @@ ---- -title: REST API -id: version-0.85-external_api_rest -original_id: external_api_rest ---- - -Home Assistant runs a web server accessible on port 8123. - -* http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -* http://IP_ADDRESS:8123/api/ is a Rest API. - -The API accepts and returns only JSON encoded objects. All API calls have to be accompanied by the header `Authorization: Bearer ABCDEFGH`. - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```bash -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. - -```python -from requests import get - -url = 'http://localhost:8123/ENDPOINT' -headers = { - 'Authorization': 'Bearer ABCDEFGH', - 'content-type': 'application/json', -} - -response = get(url, headers=headers) -print(response.text) -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on a single entity -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates the current state of an entity. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance.
- -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` diff --git a/website/versioned_docs/version-0.85/frontend_add_card.md b/website/versioned_docs/version-0.85/frontend_add_card.md deleted file mode 100644 index d4e181c3..00000000 --- a/website/versioned_docs/version-0.85/frontend_add_card.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Adding state card -id: version-0.85-frontend_add_card -original_id: frontend_add_card ---- - -The main interface of Home Assistant is a list of the current entities and their states. For each entity in the system, a state card will be rendered. State cards will show an icon, the name of the entity, when the state has last changed and the current state or a control to interact with it. - -![Cards in the frontend](/img/en/frontend/frontend-cards1.png) - -The different card types can be found [here](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary). - -Sensors, when not grouped, are shown as so-called badges on top of the state cards. - -![Badges in the frontend](/img/en/frontend/frontend-badges.png) - -The different badges are located in the file [`/src/components/entity/ha-state-label-badge.js`](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/components/entity/ha-state-label-badge.js). - -Adding a custom card type can be done with a few simple steps. For this example we will add a new state card for the domain `camera`: - - 1. Add `'camera'` to the array `DOMAINS_WITH_CARD` in the file [/common/const.ts](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/common/const.ts). - 2. Create the files `state-card-camera.js` in the folder [/state-summary/](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary). - 3. Add `import './state-card-camera.js';` to [state-card-content.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/state-summary/state-card-content.js). diff --git a/website/versioned_docs/version-0.85/frontend_add_more_info.md b/website/versioned_docs/version-0.85/frontend_add_more_info.md deleted file mode 100644 index 7f19c811..00000000 --- a/website/versioned_docs/version-0.85/frontend_add_more_info.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Adding more info dialogs -id: version-0.85-frontend_add_more_info -original_id: frontend_add_more_info ---- - -Whenever the user taps or clicks on one of the cards, a more info dialog will show. The header of this dialog will be the state card, followed by the history of this entity for the last 24 hours. Below this the more info component is rendered for that entity. The more info component can show more information or allow more ways of control. - -The more info dialog for a light allows the user to control the color and the brightness. - -The instructions to add a more info dialog are very similar to adding a new card type. This example will add a new more info component for the domain `camera`: - - 1. Add `'camera'` to the array `DOMAINS_WITH_MORE_INFO` in the file [/common/const.ts](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/common/const.ts). - 2. Create the files `more-info-camera.js` in the folder [/dialogs/more-info/controls](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/dialogs/more-info/controls). - 3. Add `import './more-info-camera.js';` to [/dialogs/more-info/controls/more-info-content.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/dialogs/more-info/controls/more-info-content.js) diff --git a/website/versioned_docs/version-0.86.0/development_environment.md b/website/versioned_docs/version-0.86.0/development_environment.md deleted file mode 100644 index 031c51ce..00000000 --- a/website/versioned_docs/version-0.86.0/development_environment.md +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.86.0-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example CentOS would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Due to Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run -``` -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is set up, perform install as for Linux. - -```bash -$ sudo apt-get update -$ sudo apt-get install python3-pip python3-dev python3-venv -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```bash -mkdir -p ../config -hass -c ../config -``` - -### Developing on OS X - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 autoconf -``` - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv . -$ source bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```bash -$ hass -``` - -## Logging - -By default logging in Home Assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` diff --git a/website/versioned_docs/version-0.86.0/documentation_index.md b/website/versioned_docs/version-0.86.0/documentation_index.md deleted file mode 100644 index a01fb597..00000000 --- a/website/versioned_docs/version-0.86.0/documentation_index.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Documentation -id: version-0.86.0-documentation_index -original_id: documentation_index ---- - -The user documentation is located at [https://www.home-assistant.io](https://www.home-assistant.io). This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. You work on your change and propose it via a Pull Request (PR). - -Once you've created a Pull Request (PR), you can see a preview of the proposed changes by clicking *Details* against Netlify checker in the checkers section of the PR as soon as deployment is complete. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process of working on the website is no different from working on Home Assistant itself. - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.3.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` (You might have to run this command as `sudo`). -- Fork the home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.io). -- In your home-assistant.io root directory, run `$ bundle` to install the gems you need. - -- Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` -- Shortcut for Debian/Ubuntu: `$ sudo apt-get install ruby ruby-dev ruby-bundler ruby-json g++ zlib1g-dev && bundle` - -Then you can work on the documentation: - -- Run `bundle exec rake generate` to generate the very first preview. This will take a couple of minutes. -- Create/edit/update a page. The components/platforms documentation is located in `source/_components/`. `source/_docs/` contains the Home Assistant documentation itself. -- Test your changes to home-assistant.io locally: run `bundle exec rake preview` and navigate to [http://127.0.0.1:4000](http://127.0.0.1:4000). While this command is working, any changes to a file are automatically detected and will update the affected pages. You will have to manually reload them in the browser though. -- Create a Pull Request (PR) against the **next** branch of home-assistant.io if your documentation is a new feature, platform, or component. -- Create a Pull Request (PR) against the **current** branch of home-assistant.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -The site generated by `bundle exec rake` is only available locally. If you are developing on a headless machine, use port forwarding: - -```bash -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` - -## Speeding up site generation - -Every release we post long changelogs to the website. This slows down generation of the website significantly! We include some tools to temporarily exclude components and blog posts that you're not working on out of the way. - -```bash -bundle exec rake isolate[filename-of-blogpost-or-component] -``` - -When you're done working on the site, run the following command to move the pages back again: - -```bash -bundle exec rake integrate -``` diff --git a/website/versioned_docs/version-0.86.0/entity_air_quality.md b/website/versioned_docs/version-0.86.0/entity_air_quality.md deleted file mode 100644 index 2e54989e..00000000 --- a/website/versioned_docs/version-0.86.0/entity_air_quality.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Air Quality Entity -sidebar_label: Air Quality -id: version-0.86.0-entity_air_quality -original_id: entity_air_quality ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| particulate_matter_2_5 | float | **Required** | The particulate matter 2.5 (<= 2.5 μm) level. -| particulate_matter_10 | float | **Required** | The particulate matter 10 (<= 10 μm) level. -| particulate_matter_0_1 | float | `None` | The particulate matter 0.1 (<= 0.1 μm) level. -| air_quality_index | float | `None` | The Air Quality Index (AQI). -| ozone | float | `None` | The O3 (ozone) level. -| carbon_monoxide | float | `None` | The CO (carbon monoxide) level. -| carbon_dioxide | float | `None` | The CO2 (carbon dioxide) level. -| sulphur_dioxide | float | `None` | The SO2 (sulphur dioxide) level. -| nitrogen_oxide | float | `None` | The N2O (nitrogen oxide) level. -| nitrogen_monoxide | float | `None` | The NO (nitrogen monoxide) level. -| nitrogen_dioxide | float | `None` | The NO2 (nitrogen dioxide) level. -| volatile_organic_compounds | float | `None` | The volatile organic compounds (VOC) level. - -Properties have to follow the units defined in the `unit_system`. - diff --git a/website/versioned_docs/version-0.86.0/external_api_rest.md b/website/versioned_docs/version-0.86.0/external_api_rest.md deleted file mode 100644 index 66df5f01..00000000 --- a/website/versioned_docs/version-0.86.0/external_api_rest.md +++ /dev/null @@ -1,519 +0,0 @@ ---- -title: REST API -id: version-0.86.0-external_api_rest -original_id: external_api_rest ---- - -Home Assistant provides a RESTful API on the same port as the web frontend. (default port is port 8123). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -* http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -* http://IP_ADDRESS:8123/api/ is a RESTful API. - -The API accepts and returns only JSON encoded objects. - -All API calls have to be accompanied by the header `Authorization: Bearer ABCDEFGH`, where `ABCDEFGH` is replaced by your token. You can obtain a token ("Long-Lived Access Token") by logging into the frontend using a web browser, and going to [your profile](https://www.home-assistant.io/docs/authentication/#your-account-profile) `http://IP_ADDRESS:8123/profile`. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```bash -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. - -```python -from requests import get - -url = 'http://localhost:8123/ENDPOINT' -headers = { - 'Authorization': 'Bearer ABCDEFGH', - 'content-type': 'application/json', -} - -response = get(url, headers=headers) -print(response.text) -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on one or more entities - comma separated. -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates the current state of an entity. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance.
- -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` diff --git a/website/versioned_docs/version-0.86.0/hassio_addon_config.md b/website/versioned_docs/version-0.86.0/hassio_addon_config.md deleted file mode 100644 index 67d1fa09..00000000 --- a/website/versioned_docs/version-0.86.0/hassio_addon_config.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.86.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use `jq` inside your shell script to parse this data. However, you might have to install `jq` as a separate package in your container (see `Dockerfile` below). - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -## Add-on Docker file - -All add-ons are based on Alpine Linux 3.6. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | no | List of supported arch: `armhf`, `aarch64`, `amd64`, `i386`. Default all. -| machine | list | no | Default it support any machine type. You can select that this add-on run only on specific machines. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| kernel_modules | bool | no | Map host kernel modules and config into add-on (readonly). -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| auth_api | bool | no | Allow access to Home Assistent user backend. - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. diff --git a/website/versioned_docs/version-0.86.0/lovelace_custom_card.md b/website/versioned_docs/version-0.86.0/lovelace_custom_card.md deleted file mode 100644 index 1dd444ce..00000000 --- a/website/versioned_docs/version-0.86.0/lovelace_custom_card.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -title: "Lovelace: Custom Cards" -id: version-0.86.0-lovelace_custom_card -original_id: lovelace_custom_card ---- - -[Lovelace](https://www.home-assistant.io/lovelace/) is our new approach to defining your user interface for Home Assistant. We offer a lot of built-in cards, but you're not just limited to the ones that we decided to include in the Lovelace UI. You can build and use your own! - -## API - -You define your custom card as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). It's up to you to decide how to render your DOM inside your element. You can use Polymer, Angular, Preact or any other popular framework (except for React – [more info on React here](https://custom-elements-everywhere.com/#react)). - -```js -const element = document.createElement('some-custom-card'); -``` - -Home Assistant will call `setConfig(config)` when the configuration changes (rare). If you throw an exception if the configuration is invalid, Lovelace will render an error card to notify the user. - -```js -try { - element.setConfig(config); -} catch (err) { - showErrorCard(err.message, config); -} -``` - -Home Assistant will set the `hass` property when the state of Home Assistant changes (frequent). Whenever the state changes, the component will have to update itself to represent the latest state. - -```js -element.hass = hass; -``` - -Your card can define a `getCardSize` method that returns the size of your card as a number. A height of 1 is equivalent to 50 pixels. This will help Home Assistant distribute the cards evenly over the columns. A card size of `1` will be assumed if the method is not defined. - -```js -if ('getCardSize' in element) { - return element.getCardSize(); -} else { - return 1; -} -``` - -## Defining your card - -Create a new file in your Home Assistant config dir as `/www/content-card-example.js` and put in the following contents: - -```js -class ContentCardExample extends HTMLElement { - set hass(hass) { - if (!this.content) { - const card = document.createElement('ha-card'); - card.header = 'Example card'; - this.content = document.createElement('div'); - this.content.style.padding = '0 16px 16px'; - card.appendChild(this.content); - this.appendChild(card); - } - - const entityId = this.config.entity; - const state = hass.states[entityId]; - const stateStr = state ? state.state : 'unavailable'; - - this.content.innerHTML = ` - The state of ${entityId} is ${stateStr}! -

- - `; - } - - setConfig(config) { - if (!config.entity) { - throw new Error('You need to define an entity'); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return 3; - } -} - -customElements.define('content-card-example', ContentCardExample); -``` - -## Referencing your new card - -In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `/www` directory, it will be accessible in your browser via the url `/local/` (if you have recently added the www folder you will need to re-start home assistant for files to be picked up). - -```yaml -# Example Lovelace configuration -resources: - - url: /local/content-card-example.js - type: js -views: -- name: Example - cards: - - type: "custom:content-card-example" - entity: input_boolean.switch_tv -``` - -## Advanced example - -Resources to load in Lovelace can be imported as a JS script, an HTML import or as a JS module import. Below is an example of a custom card using JS modules that does all the fancy things. - -![Screenshot of the wired card](/img/en/frontend/lovelace-ui-custom-card-screenshot.png) - -Create a new file in your Home Assistant config dir as `/www/wired-cards.js` and put in the following contents: - -```js -import 'https://unpkg.com/wired-card@0.6.5/wired-card.js?module'; -import 'https://unpkg.com/wired-toggle@0.6.5/wired-toggle.js?module'; -import { - LitElement, html -} from 'https://unpkg.com/@polymer/lit-element@^0.5.2/lit-element.js?module'; - -function loadCSS(url) { - const link = document.createElement('link'); - link.type = 'text/css'; - link.rel = 'stylesheet'; - link.href = url; - document.head.appendChild(link); -} - -loadCSS('https://fonts.googleapis.com/css?family=Gloria+Hallelujah'); - -class WiredToggleCard extends LitElement { - static get properties() { - return { - hass: Object, - config: Object, - } - } - - _render({ hass, config }) { - return html` - - - ${config.entities.map(ent => hass.states[ent]).map((state) => - html` -
- ${state.attributes.friendly_name} - -
- ` - )} -
- `; - } - - setConfig(config) { - if (!config.entities) { - throw new Error('You need to define entities'); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return this.config.entities.length + 1; - } - - _toggle(state) { - this.hass.callService('homeassistant', 'toggle', { - entity_id: state.entity_id - }); - } -} -customElements.define('wired-toggle-card', WiredToggleCard); -``` - -And for your configuration: - -```yaml -# Example Lovelace configuration -resources: - - url: /local/wired-cards.js - type: module -views: -- name: Example - cards: - - type: "custom:wired-toggle-card" - entities: - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_livingroom - - input_boolean.switch_tv -``` diff --git a/website/versioned_docs/version-0.87.0/area_registry_index.md b/website/versioned_docs/version-0.87.0/area_registry_index.md deleted file mode 100644 index 33b4e692..00000000 --- a/website/versioned_docs/version-0.87.0/area_registry_index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Area Registry -sidebar_label: Introduction -id: version-0.87.0-area_registry_index -original_id: area_registry_index ---- - -The area registry is a registry where Home Assistant keeps track of areas. An area represents a physical location for Home Assistant. It can be used to place devices in different areas. - -| Attribute | Description | -| --------- | ----------- | -| id | Unique ID of area (generated by Home Assistant) -| name | Name of this area diff --git a/website/versioned_docs/version-0.87.0/development_environment.md b/website/versioned_docs/version-0.87.0/development_environment.md deleted file mode 100644 index 562e8d29..00000000 --- a/website/versioned_docs/version-0.87.0/development_environment.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.87.0-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example CentOS would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Due to Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run - -```bash -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is set up, perform install as for Linux. - -```bash -$ sudo apt-get update -$ sudo apt-get install python3-pip python3-dev python3-venv -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```bash -$ mkdir -p ../config -$ hass -c ../config -``` - -### Developing on OS X - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 autoconf -``` - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv . -$ source bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```bash -$ hass -``` - -## Logging - -By default logging in Home Assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` diff --git a/website/versioned_docs/version-0.87.0/device_registry_index.md b/website/versioned_docs/version-0.87.0/device_registry_index.md deleted file mode 100644 index 515d2ce4..00000000 --- a/website/versioned_docs/version-0.87.0/device_registry_index.md +++ /dev/null @@ -1,75 +0,0 @@ ---- -title: Device Registry -sidebar_label: Introduction -id: version-0.87.0-device_registry_index -original_id: device_registry_index ---- - -The device registry is a registry where Home Assistant keeps track of devices. A device is represented in Home Assistant via one or more entities. For example, a battery-powered temperature and a humidity sensor might expose entities for temperature, humidity and battery level. - -Device registry overview - -| Attribute | Description | -| --------- | ----------- | -| id | Unique ID of device (generated by Home Assistant) -| name | Name of this device -| connections | A set of tuples of `(connection_type, connection identifier)`. Connection types are defined in the device registry module. -| identifiers | Set of identifiers. They identify the device in the outside world. An example is a serial number. -| manufacturer | The manufacturer of the device. -| model | The model of the device. -| config_entries | Config entries that are linked to this device. -| sw_version | The firmware version of the device. -| via_hub | Identifier of a device that routes messages between this device and Home Assistant. Examples of such devices are hubs. This is used to show device topology in Home Assistant. -| area_id | The Area which the device is placed in. - -## Defining devices - -> Entity device info is only read if the entity is loaded via a [config entry](config_entries_index.md). - -Each entity is able to define a device via the `device_info` property. This property is read when an entity is added to Home Assistant via a config entry. A device will be be matched up with an existing device via supplied identifiers and connections, like serial numbers or MAC addresses. - -```python -# Inside a platform -class HueLight(LightEntity): - - @property - def device_info(self): - return { - 'identifiers': { - # Serial numbers are unique identifiers within a specific domain - (hue.DOMAIN, self.unique_id) - }, - 'name': self.name, - 'manufacturer': self.light.manufacturername, - 'model': self.light.productname, - 'sw_version': self.light.swversion, - 'via_hub': (hue.DOMAIN, self.api.bridgeid), - } - -``` - -Components are also able to register devices in the case that there are no entities representing them. An example is a hub that communicates with the lights. - -```python -# Inside a component -from homeassistant.helpers import device_registry as dr - -device_registry = await dr.async_get_registry(hass) - -device_registry.async_get_or_create( - config_entry=entry.entry_id, - connections={ - (dr.CONNECTION_NETWORK_MAC, config.mac) - }, - identifiers={ - (DOMAIN, config.bridgeid) - }, - manufacturer='Signify', - name=config.name, - model=config.modelid, - sw_version=config.swversion, -) -``` diff --git a/website/versioned_docs/version-0.87.0/documentation_create_page.md b/website/versioned_docs/version-0.87.0/documentation_create_page.md deleted file mode 100644 index 386e9162..00000000 --- a/website/versioned_docs/version-0.87.0/documentation_create_page.md +++ /dev/null @@ -1,150 +0,0 @@ ---- -title: Create a new page -id: version-0.87.0-documentation_create_page -original_id: documentation_create_page ---- - -For a platform or component page, the fastest way is to make a copy of an existing page and edit it. The [Component overview](https://www.home-assistant.io/components/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages. - -Please honor the [Standards](documentation_standards.md) we have for the documentation. - -If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers. - -```text ---- -layout: page -title: "Awesome Sensor" -description: "home-assistant.io web presence" -date: 2015-06-17 08:00 -sidebar: true -comments: false -sharing: true -footer: true -ha_release: "0.38" -ha_category: Sensor -ha_iot_class: "Local Polling" -ha_qa_scale: silver ---- - -Content... Written in markdown. - -### {% linkable_title Linkable Header %} -... -``` - -Please keep in mind that if the `date:` entry is in the future then the page will not show up. - -Additional keys for the file header: - -- `logo`: Please check the separate section below. -- `ha_release`: The release when the integration was included, e.g., "0.38". If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`. -- `ha_category`: This entry is used to group the integration on the [Components overview](https://www.home-assistant.io/components/). -- `ha_iot_class`: [IoT class](https://www.home-assistant.io/blog/2016/02/12/classifying-the-internet-of-things) is the classifier for the device's behavior. -- `ha_qa_scale`: [Quality scale](https://www.home-assistant.io/docs/quality_scale/) is the representation of the integration's quality. - -There are [pre-defined variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation. - -A couple of points to remember: - -- Document the needed steps to retrieve API keys or access token for the third party service or device if needed. -- Add screenshots to support the user where it makes sense. -- Add the type of the device(s) (incl. firmware) you have tested when you know that there are multiple out there. - -### Components and platforms - -If you have a component that is taking care of setting up platforms then you don't need to create a new page for every supported platform. Simply add all supported types to `ha_category:` and use `redirect_from:` to list the dummy URL of the platforms. - -```text -... -ha_category: - - DIY - - Binary Sensor - - Switch -redirect_from: - - /components/binary_sensor.raspihats/ - - /components/switch.raspihats/ ---- -... -``` - -### Configuration - -Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file. - -The **Configuration Variables** section must use the `{% configuration %} ... {% endconfiguration %}` tag. - -```text -{% configuration %} -api_key: - description: The API key to access the service. - required: true - type: string -name: - description: Name to use in the frontend. - required: false - default: The default name to use in the frontend. - type: string -monitored_conditions: - description: Conditions to display in the frontend. - required: true - type: map - keys: - weather: - description: A human-readable text summary. - temperature: - description: The current temperature. -{% endconfiguration %} -``` - -Available keys: - -- **`description:`**: That the variable is about. -- **`required:`**: If the variable is required. - -```text -required: true #=> Required -required: false #=> Optional -required: inclusive #=> Inclusive -required: exclusive #=> Exclusive -required: any string here #=> Any string here -``` -- **`type:`**: The type of the variable. Allowed entries: `boolean`, `string`, `integer`, `float`, `time`, `template`, `device_class`, `icon` or `map`/`list` (for a list of entries). For multiple possibilities use `[string, integer]`. If you use `map`/`list` then should define `keys:` (see the [`template` sensor](https://www.home-assistant.io/components/sensor.template/) for an example). If you use `boolean`, then `default:` must be defined. -- **`default:`**: The default value for the variable. - -### Embedding Code - -You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in back-ticks. - -When you're writing code that is to be executed on the terminal, prefix it with `$`. - -### Templates - -For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) [Jinja](http://jinja.pocoo.org/) is used. Check the [Documentation Standards](documentation_standards.md) for further details. - -If you are don't escape templates then they will be rendered and appear blank on the website. - -### HTML - -The direct usage of HTML is supported but not recommended. The note boxes are an exception. - -```html -

- You need to enable telnet on your router. -

-``` - -### Images, icons and logos - -The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent. - -| Type | Location | -| :----------- |:----------------------------------------------| -| logos | source/images/supported_brands | -| blog | source/images/blog | -| screenshots | source/images/components | - -Not everything (product, component, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/). - -### Linking From The Sidebar - -If you are adding a new page that requires linking from the sidebar, you need to edit the `docs_navigation.html` file in `source/_includes/asides/docs_navigation.html`. diff --git a/website/versioned_docs/version-0.87.0/documentation_standards.md b/website/versioned_docs/version-0.87.0/documentation_standards.md deleted file mode 100644 index 561b8a45..00000000 --- a/website/versioned_docs/version-0.87.0/documentation_standards.md +++ /dev/null @@ -1,126 +0,0 @@ ---- -title: Standards -id: version-0.87.0-documentation_standards -original_id: documentation_standards ---- - -To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation. - -## General Documentation - -* The language of the documentation should be American-English. -* Don't put two spaces after a period and avoid the "Oxford comma". -* There is no limit for the line length. You are allowed to write in a flowing text style. This will make it easier to use the GitHub online editor in the future. -* Be objective and not gender favoring, polarizing, race related or religion inconsiderate. -* The case of brand names, services, protocols, components and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select". -* All headings should use the `{% linkable_title %}` tag. -* Do not use ALL CAPITALS for emphasis - use italics instead. - -## Component and Platform Pages - -* The **Configuration Variables** section must use the `{% configuration %}` tag. -* Configuration variables must document the requirement status (`false` or `true`). -* Configuration variables must document the default value, if any. -* Configuration variables must document the accepted value types (see [Configuration variables details](documentation_create_page.md#configuration)). - * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`). -* Use YAML sequence syntax in the sample code if it is supported. -* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated. - * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`. - * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note. -* Component and platform names should be a link to their respective documentation pages. - -Example configuration block - -```yaml -{% configuration %} -some_key: - description: This is a description of what this key is for. - required: false - type: string - default: Optional default value - leave out if there isn't one -{% endconfiguration %} -``` - -## Templates - -* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the `{% raw %}` tag. -* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`. -* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)): - * `friendly_name` - * Single-line templates: - * `value_template` - * `level_template` - * `icon_template` - * Children of `data_template` -* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks): - * Strings inside of templates: - * States - * Entity IDs - * `unit_of_measurement` -* No whitespace around pipe character (`|`) for Jinja2 filters. -* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}). -* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}). -* Do not quote values for: - * `device_class` - * `platform` - * `condition` - * `service` - -## Renaming Pages - -It can happen that a component or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old component/platform name, to the page in a [note](/developers/documentation/create_page/#html). - -```text ---- -... -redirect_from: /getting-started/android/ ---- -``` - -Adding a redirect also applies if you move content around in the [documentation](/docs/). - -## Single vs. Double Quotation Marks - -Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required). - -### Examples - -#### Double Quotes Outside, Single Quotes Inside (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}" -``` - -#### Single Quotes Outside, Double Quotes Inside (Invalid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}' -``` - -#### Multi-Line Template (Valid) - - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: >- - {% if trigger.to_state.name == 'Dale\'s Bedroom' %} - Someone's in your base, killing your noobs! - {% else %} - It's just another door. - {% endif %} -``` - diff --git a/website/versioned_docs/version-0.87.0/frontend_architecture.md b/website/versioned_docs/version-0.87.0/frontend_architecture.md deleted file mode 100644 index cb91f332..00000000 --- a/website/versioned_docs/version-0.87.0/frontend_architecture.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Home Assistant Frontend Architecture -sidebar_label: Architecture -id: version-0.87.0-frontend_architecture -original_id: frontend_architecture ---- - -The Home Assistant frontend is built using web components. This is a modern web technology allowing us to encapsulate templates, styling and logic into a single file and expose it as an HTML tag in the browser. These components are composable, allowing a very dynamic and powerful foundation of our application. - -## Structure - -The Home Assistant frontend can be broken up in 4 parts: - -### Bootstrap - -File: `src/entrypoints/core.js` - -This is a very tiny script which is the first thing that is loaded on the page. It is responsible for checking for authentication credentials and setting up the websocket connection with the backend. - -The script allows us to start downloading the data while also downloading the rest of the UI in parallel. - -### App shell - -File: `src/entrypoints/app.js` - -This is everything that is required to render the sidebar and handle the routing. - -### Panels - -Folder: `src/panels/` - -Each page in Home Assistant is a panel. Components can register extra panels to be shown to the user. Examples of panels are "states", "map", "logbook" and "history". - -### More info dialog - -Folder: `src/dialogs/more-info` - -This is a dialog that allows users to see more information about an entity and control its state. - -The more info dialog can be triggered from any component in the app by firing a DOM event `hass-more-info` with as detail `{ entityId: 'light.kitchen' }`. - -## Data Flow - -The frontend leverages the [Websocket API](external_api_websocket.md) and the [Rest API](external_api_rest.md) to interact with Home Assistant. - -The data is made available as the `hass` property which is passed down to every component. The `hass` property contains the whole application state and has methods to call APIs. - -We use a unidirectional data flow (like Flux, Redux). When you make a change in the backend (like turning on a light), the `hass` object will be updated at the root of the application and will be made available to every component that needs it. - -## Routing - -The frontend uses decentralized routing. Each component only knows enough about the routing to know how to handle the part it's responsible for. Further routing is passed down the component tree. - -For example, the `` main component will look at the first part of the url to decide which panel should be loaded. Each panel can have its own mapping between the url and what content to show. - -For the routing, we use the [``](https://www.polymer-project.org/blog/routing) web component. - -## Bundling - -We use Webpack to bundle up the application. We have various gulp scripts to help with generating the icon set and the index.html. - -We're aggresively code splitting our application by leveraging the dynamic import syntax (`import('path/to/some/file.js')`). When encountering an `import()`, Webpack will split the code into different chunks and makes sure that they are loaded when needed. - - diff --git a/website/versioned_docs/version-0.87.0/frontend_development.md b/website/versioned_docs/version-0.87.0/frontend_development.md deleted file mode 100644 index 27a7b4df..00000000 --- a/website/versioned_docs/version-0.87.0/frontend_development.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: Frontend development -sidebar_label: Development -id: version-0.87.0-frontend_development -original_id: frontend_development ---- - -The Home Assistant frontend is built using web components and powered by the [Polymer](https://www.polymer-project.org/) framework. - -> Do not use development mode in production. Home Assistant uses aggressive caching to improve the mobile experience. This is disabled during development so that you do not have to restart the server in between changes. - -## Setting up the environment - -> All commands below need to be run from inside the home-assistant-polymer repository. - -### Getting the code - -First step is to fork the [home-assistant-polymer repository][hass-polymer] and add the upstream remote. You can place the forked repository anywhere on your system. - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant-polymer.git -$ cd home-assistant-polymer -$ git remote add upstream https://github.com/home-assistant-polymer/home-assistant-polymer.git -``` - -### Configuring Home Assistant - -You will need to have an instance of Home Assistant set up. See our guide on [setting up a development environment](https://developers.home-assistant.io/docs/en/development_environment.html). - -Next step is to configure Home Assistant to use the development mode for the frontend. Do this by updating the frontend config in your `configuration.yaml` and set the path to the home-assistant-polymer repository that you cloned in the last step: - -```yaml -frontend: - # Example absolute path: /home/paulus/dev/hass/home-assistant-polymer - development_repo: -``` - -### Installing Node.js - -Node.js is required to build the frontend. The preferred method of installing node.js is with [nvm](https://github.com/creationix/nvm). Install nvm using the instructions in the [README](https://github.com/creationix/nvm#install-script), and install the correct node.js by running the following command: - -```bash -$ nvm install -``` - -[Yarn](https://yarnpkg.com/en/) is used as the package manager for node modules. [Install yarn using the instructions here.](https://yarnpkg.com/en/docs/install) - -Next, development dependencies need to be installed to bootstrap the frontend development environment. First activate the right Node version and then download all the dependencies: - -```bash -$ nvm use -$ script/bootstrap -``` - -## Development - -During development, you will need to run the development script to maintain a development build of the frontend that auto updates when you change any of the source files. To run this server, run: - -```bash -$ nvm use -$ script/develop -``` - -Make sure you have cache disabled and correct settings to avoid stale content: - -> Instructions are for Google Chrome - -1. Disable cache by ticking the box in `Network` > `Disable cache` - -

- -

- -2. Enable Bypass for network in `Application` > `Service Workers` > `Bypass for network` - -

- -

- -## Creating pull requests - -If you're planning on issuing a PR back to the Home Assistant codebase you need to fork the polymer project and add your fork as a remote to the Home Assistant Polymer repo. - -```bash -$ git remote add fork -``` - -When you've made your changes and are ready to push them change to the working directory for the polymer project and then push your changes - -``` bash -$ git add -A -$ git commit -m "Added new feature X" -$ git push -u fork HEAD -``` - -## Building the Polymer frontend - -If you're making changes to the way the frontend is packaged, it might be necessary to try out a new packaged build of the frontend in the main repository (instead of pointing it at the frontend repo). To do so, first build a production version of the frontend by running `script/build_frontend`. - -To test it out inside Home assistant, run the following command from the main Home Assistant repository: - -```bash -$ pip3 install -e /path/to/home-assistant-polymer/ -$ hass --skip-pip -``` - -[hass-polymer]: https://github.com/home-assistant/home-assistant-polymer diff --git a/website/versioned_docs/version-0.88.0/development_guidelines.md b/website/versioned_docs/version-0.88.0/development_guidelines.md deleted file mode 100644 index 91104bd4..00000000 --- a/website/versioned_docs/version-0.88.0/development_guidelines.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -title: Style guidelines -id: version-0.88.0-development_guidelines -original_id: development_guidelines ---- - -Home Assistant enforces strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. We automatically test every pull request as part of the linting process with [Coveralls](https://coveralls.io/github/home-assistant/home-assistant) and [Travis CI](https://travis-ci.org/home-assistant/home-assistant). - -Summary of the most relevant points: - -- Line length is limited to 79 characters (see below). -- Use 4 spaces per indentation level. We don't use tabs. -- Comments should be full sentences and end with a period. -- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered. -- Constants and the content of lists and dictionaries should be in alphabetical order. -- Avoid trailing whitespace but surround binary operators with a single space. -- Line separator should be set to `LF`. - -The maximum line length comes directly from the [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/#maximum-line-length), and is also used by the Python standard library. All code must pass these linting checks, and no exceptions will be made. There have already been numerous requests to increase the maximum line length, but after evaluating the options, the Home Assistant maintainers have decided to stay at 79 characters. This decision is final. - -Those points may require that you adjust your IDE or editor settings. - -## Our recommendations - -For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code unified. - -### Quotes - -Use single quotes `'` for single word and `"` for multiple words or sentences. - -```python -ATTR_WATERLEVEL = 'level' -CONF_ATTRIBUTION = "Data provided by the WUnderground weather service" -SENSOR_TYPES = { - 'alerts': ['Alerts', None], -} -``` - -### File headers - -The docstring in the file header should describe what the file is about. - -```python -"""Support for MQTT lights.""" -``` - -### Requirements - -Please place [Platform requirements](creating_platform_code_review.md#1-requirements) right after the imports. - -```python -[...] -from homeassistant.helpers.entity import Entity - -REQUIREMENTS = ['xmltodict==0.11.0'] -``` - -### Log messages - -There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. Try to avoid brackets and additional quotes around the output to make it easier for users to parse the log. A widely style is shown below but you are free to compose the messages as you like. - -```python -_LOGGER.error("No route to device: %s", self._resource) -``` - -```bash -2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18 -``` - -Don't print out wrong API keys, tokens, usernames, or passwords. -Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` in anything else. - -### Ordering of imports - -Instead of order the imports manually, use [`isort`](https://github.com/timothycrosley/isort). - -```bash -$ pip3 install isort -$ isort homeassistant/components/sensor/fixer.py -``` - -### Use new style string formatting - -Prefer [new style string formatting](https://www.python.org/dev/peps/pep-3101/) over old. - -```python -"{} {}".format('New', 'style') -"%s %s" % ('Old', 'style') -``` - -Except when doing logging here the format is: - -```python -_LOGGER.info("Can't connect to the webservice %s at %s", string1, string2) -``` diff --git a/website/versioned_docs/version-0.88.0/entity_index.md b/website/versioned_docs/version-0.88.0/entity_index.md deleted file mode 100644 index 292414b8..00000000 --- a/website/versioned_docs/version-0.88.0/entity_index.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Entity -sidebar_label: Introduction -id: version-0.88.0-entity_index -original_id: entity_index ---- - -Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating. - -Below is an example switch entity that keeps track of their state in memory. - -```python -from homeassistant.components.switch import SwitchDevice - -class MySwitch(SwitchDevice): - - def __init__(self): - self._is_on = False - - @property - def name(self): - """Name of the device.""" - return 'My Switch' - - @property - def is_on(self): - """If the switch is currently on or off.""" - return self._is_on - - def turn_on(self, **kwargs): - """Turn the switch on.""" - self._is_on = True - - def turn_off(self, **kwargs): - """Turn the switch off.""" - self._is_on = False -``` - -That's all there is to it to build a switch entity! Continue reading to learn more or check out the [video tutorial](https://youtu.be/Cfasc9EgbMU?t=737). - -## Updating the entity - -An entity represents a device. There are various strategies to keep your entity in sync with the state of the device, the most popular one being polling. - -### Polling - -With polling, Home Assistant will ask the entity from time to time (depending on the update interval of the component) to fetch the latest state. Home Assistant will poll an entity when the `should_poll` property returns `True` (the default value). You can either implement your update logic using `update()` or the async method `async_update()`. This method should fetch the latest state from the device and store it in an instance variable for the properties to return it. - -### Subscribing to updates - -When you subscribe to updates, your code is responsible for letting Home Assistant know that an update is available. Make sure you have the `should_poll` property return `False`. - -Whenever you receive new state from your subscription, you can tell Home Assistant that an update is available by calling `schedule_update_ha_state()` or async callback `async_schedule_update_ha_state()`. Pass in the boolean `True` to the method if you want Home Assistant to call your update method before writing the update to Home Assistant. - -## Generic properties - -The entity base class has a few properties that are common among all entities in Home Assistant. These can be added to any entity regardless of the type. All these properties are optional and don't need to be implemented. - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| assumed_state | boolean | `False` | Return `True` if the state is based on our assumption instead of reading it from the device. -| available | boolean | `True` | Indicate if Home Assistant is able to read the state and control the underlying device. -| device_state_attributes | dict | `None` | Extra information to store in the state machine. It needs to be information that further explains the state, it should not be static information like firmware version. See [below](entity_index.md#standard_attributes) for details of standard attributes. -| entity_picture | URL | `None` | Url of a picture to show for the entity. -| name | string | `None` | Name of the entity -| should_poll | boolean | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](#methods). -| unique_id | string | `None` | A unique identifier for this entity. Needs to be unique within a platform (ie `light.hue`). Should not be configurable by the user or be changeable. [Learn more.](entity_registry_index.md#unique-id-requirements) - -## Advanced properties - -The following properties are also available on entities. However, they are for advanced use only and should be used with caution. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| force_update | boolean | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine. -| hidden | boolean | `False` | Indicate if the entity should not be shown on the frontend. -| icon | icon | `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all devices. - -## Standard attributes - -The following `device_state_attributes` are considered standard and should follow the convention below. The constant should be imported from `homeassistant/const.py`. - -| Name | Type | Unit | Constant | Description -| ---- | ---- | ---- | -------- | ----------- -| battery_charging | boolean | N/A | `ATTR_BATTERY_CHARGING` | Battery charging status of the entity, shown as a boolean `true` or `false`. If charging is not supported, then this attribute should not be created. -| battery_level | integer | % | `ATTR_BATTERY_LEVEL` | Battery level of the entity, shown as an integer percentage between 0-100. - -## Lifecycle hooks - -Use these lifecycle hooks to execute code when certain events happen to the entity. All lifecycle hooks are async methods. - -### `async_added_to_hass()` - -Called when an entity has their entity_id and hass object assigned, before it is written to the state machine for the first time. Example uses: restore the state or subscribe to updates. - -### `async_will_remove_from_hass()` - -Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates. - -## Changing the entity model - -If you want to add a new feature to an entity or any of its subtypes (light, switch, etc), you will need to propose it first in our [architecture repo](https://github.com/home-assistant/architecture/issues). Only additions will be considered that are common features among various vendors. diff --git a/website/versioned_docs/version-0.88.0/frontend_development.md b/website/versioned_docs/version-0.88.0/frontend_development.md deleted file mode 100644 index a5345354..00000000 --- a/website/versioned_docs/version-0.88.0/frontend_development.md +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: Frontend development -sidebar_label: Development -id: version-0.88.0-frontend_development -original_id: frontend_development ---- - -The Home Assistant frontend is built using web components and powered by the [Polymer](https://www.polymer-project.org/) framework. - -> Do not use development mode in production. Home Assistant uses aggressive caching to improve the mobile experience. This is disabled during development so that you do not have to restart the server in between changes. - -## Setting up the environment - -> All commands below need to be run from inside the home-assistant-polymer repository. - -### Getting the code - -First step is to fork the [home-assistant-polymer repository][hass-polymer] and add the upstream remote. You can place the forked repository anywhere on your system. - -```bash -$ git clone git@github.com:YOUR_GIT_USERNAME/home-assistant-polymer.git -$ cd home-assistant-polymer -$ git remote add upstream https://github.com/home-assistant/home-assistant-polymer.git -``` - -### Configuring Home Assistant - -You will need to have an instance of Home Assistant set up. See our guide on [setting up a development environment](https://developers.home-assistant.io/docs/en/development_environment.html). - -Next step is to configure Home Assistant to use the development mode for the frontend. Do this by updating the frontend config in your `configuration.yaml` and set the path to the home-assistant-polymer repository that you cloned in the last step: - -```yaml -frontend: - # Example absolute path: /home/paulus/dev/hass/home-assistant-polymer - development_repo: -``` - -### Installing Node.js - -Node.js is required to build the frontend. The preferred method of installing node.js is with [nvm](https://github.com/creationix/nvm). Install nvm using the instructions in the [README](https://github.com/creationix/nvm#install-script), and install the correct node.js by running the following command: - -```bash -$ nvm install -``` - -[Yarn](https://yarnpkg.com/en/) is used as the package manager for node modules. [Install yarn using the instructions here.](https://yarnpkg.com/en/docs/install) - -Next, development dependencies need to be installed to bootstrap the frontend development environment. First activate the right Node version and then download all the dependencies: - -```bash -$ nvm use -$ script/bootstrap -``` - -## Development - -During development, you will need to run the development script to maintain a development build of the frontend that auto updates when you change any of the source files. To run this server, run: - -```bash -$ nvm use -$ script/develop -``` - -Make sure you have cache disabled and correct settings to avoid stale content: - -> Instructions are for Google Chrome - -1. Disable cache by ticking the box in `Network` > `Disable cache` - -

- -

- -2. Enable Bypass for network in `Application` > `Service Workers` > `Bypass for network` - -

- -

- -## Creating pull requests - -If you're planning on issuing a PR back to the Home Assistant codebase you need to fork the polymer project and add your fork as a remote to the Home Assistant Polymer repo. - -```bash -$ git remote add fork -``` - -When you've made your changes and are ready to push them change to the working directory for the polymer project and then push your changes - -``` bash -$ git add -A -$ git commit -m "Added new feature X" -$ git push -u fork HEAD -``` - -## Building the Polymer frontend - -If you're making changes to the way the frontend is packaged, it might be necessary to try out a new packaged build of the frontend in the main repository (instead of pointing it at the frontend repo). To do so, first build a production version of the frontend by running `script/build_frontend`. - -To test it out inside Home assistant, run the following command from the main Home Assistant repository: - -```bash -$ pip3 install -e /path/to/home-assistant-polymer/ -$ hass --skip-pip -``` - -[hass-polymer]: https://github.com/home-assistant/home-assistant-polymer diff --git a/website/versioned_docs/version-0.88.0/lovelace_custom_card.md b/website/versioned_docs/version-0.88.0/lovelace_custom_card.md deleted file mode 100644 index c888843b..00000000 --- a/website/versioned_docs/version-0.88.0/lovelace_custom_card.md +++ /dev/null @@ -1,227 +0,0 @@ ---- -title: Lovelace: Custom Cards -id: version-0.88.0-lovelace_custom_card -original_id: lovelace_custom_card ---- - -[Lovelace](https://www.home-assistant.io/lovelace/) is our new approach to defining your user interface for Home Assistant. We offer a lot of built-in cards, but you're not just limited to the ones that we decided to include in the Lovelace UI. You can build and use your own! - -## API - -You define your custom card as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). It's up to you to decide how to render your DOM inside your element. You can use Polymer, Angular, Preact or any other popular framework (except for React – [more info on React here](https://custom-elements-everywhere.com/#react)). - -```js -const element = document.createElement('some-custom-card'); -``` - -Home Assistant will call `setConfig(config)` when the configuration changes (rare). If you throw an exception if the configuration is invalid, Lovelace will render an error card to notify the user. - -```js -try { - element.setConfig(config); -} catch (err) { - showErrorCard(err.message, config); -} -``` - -Home Assistant will set the `hass` property when the state of Home Assistant changes (frequent). Whenever the state changes, the component will have to update itself to represent the latest state. - -```js -element.hass = hass; -``` - -Your card can define a `getCardSize` method that returns the size of your card as a number. A height of 1 is equivalent to 50 pixels. This will help Home Assistant distribute the cards evenly over the columns. A card size of `1` will be assumed if the method is not defined. - -```js -if ('getCardSize' in element) { - return element.getCardSize(); -} else { - return 1; -} -``` - -## Defining your card - -Create a new file in your Home Assistant config dir as `/www/content-card-example.js` and put in the following contents: - -```js -class ContentCardExample extends HTMLElement { - set hass(hass) { - if (!this.content) { - const card = document.createElement('ha-card'); - card.header = 'Example card'; - this.content = document.createElement('div'); - this.content.style.padding = '0 16px 16px'; - card.appendChild(this.content); - this.appendChild(card); - } - - const entityId = this.config.entity; - const state = hass.states[entityId]; - const stateStr = state ? state.state : 'unavailable'; - - this.content.innerHTML = ` - The state of ${entityId} is ${stateStr}! -

- - `; - } - - setConfig(config) { - if (!config.entity) { - throw new Error('You need to define an entity'); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return 3; - } -} - -customElements.define('content-card-example', ContentCardExample); -``` - -## Referencing your new card - -In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `/www` directory, it will be accessible in your browser via the url `/local/` (if you have recently added the www folder you will need to re-start home assistant for files to be picked up). - -```yaml -# Example Lovelace configuration -resources: - - url: /local/content-card-example.js - type: js -views: -- name: Example - cards: - - type: "custom:content-card-example" - entity: input_boolean.switch_tv -``` - -## Advanced example - -Resources to load in Lovelace can be imported as a JS script, an HTML import or as a JS module import. Below is an example of a custom card using JS modules that does all the fancy things. - -![Screenshot of the wired card](/img/en/frontend/lovelace-ui-custom-card-screenshot.png) - -Create a new file in your Home Assistant config dir as `/www/wired-cards.js` and put in the following contents: - -```js -import "https://unpkg.com/wired-card@0.8.1/wired-card.js?module"; -import "https://unpkg.com/wired-toggle@0.8.0/wired-toggle.js?module"; -import { - LitElement, - html, - css -} from "https://unpkg.com/lit-element@2.0.1/lit-element.js?module"; - -function loadCSS(url) { - const link = document.createElement("link"); - link.type = "text/css"; - link.rel = "stylesheet"; - link.href = url; - document.head.appendChild(link); -} - -loadCSS("https://fonts.googleapis.com/css?family=Gloria+Hallelujah"); - -class WiredToggleCard extends LitElement { - static get properties() { - return { - hass: {}, - config: {} - }; - } - - render() { - return html` - - ${this.config.entities.map(ent => { - const stateObj = this.hass.states[ent]; - return stateObj - ? html` -
- ${stateObj.attributes.friendly_name} - -
- ` - : html` -
Entity ${ent} not found.
- `; - })} -
- `; - } - - setConfig(config) { - if (!config.entities) { - throw new Error("You need to define entities"); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return this.config.entities.length + 1; - } - - _toggle(state) { - this.hass.callService("homeassistant", "toggle", { - entity_id: state.entity_id - }); - } - - static get styles() { - return css` - :host { - font-family: "Gloria Hallelujah", cursive; - } - wired-card { - background-color: white; - padding: 16px; - display: block; - font-size: 18px; - } - .state { - display: flex; - justify-content: space-between; - padding: 8px; - align-items: center; - } - .not-found { - background-color: yellow; - font-family: sans-serif; - font-size: 14px; - padding: 8px; - } - wired-toggle { - margin-left: 8px; - } - `; - } -} -customElements.define("wired-toggle-card", WiredToggleCard); -``` - -And for your configuration: - -```yaml -# Example Lovelace configuration -resources: - - url: /local/wired-cards.js - type: module -views: -- name: Example - cards: - - type: "custom:wired-toggle-card" - entities: - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_livingroom - - input_boolean.switch_tv -``` diff --git a/website/versioned_docs/version-0.89.0/app_integration_index.md b/website/versioned_docs/version-0.89.0/app_integration_index.md deleted file mode 100644 index 429aea1f..00000000 --- a/website/versioned_docs/version-0.89.0/app_integration_index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Native App Integration -sidebar_label: Introduction -id: version-0.89.0-app_integration_index -original_id: app_integration_index ---- - -This guide describes how to build a native Home Assistant app that communicates with Home Assistant and offers a seamless integration. Below is a list of the things that we will discuss in this guide. - -- Allow the user to establish a connection and authenticate with their own Home Assistant instance. -- Send location and device info back to Home Assistant. -- Call services, fire events and render templates. -- A view to control the house via an authenticated webview. diff --git a/website/versioned_docs/version-0.89.0/app_integration_sending_data.md b/website/versioned_docs/version-0.89.0/app_integration_sending_data.md deleted file mode 100644 index 7b79a28e..00000000 --- a/website/versioned_docs/version-0.89.0/app_integration_sending_data.md +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Sending data home -id: version-0.89.0-app_integration_sending_data -original_id: app_integration_sending_data ---- - -Once you have registered your app with the mobile app component, you can start interacting with Home Assistant via the provided webhook information. - -The first step is to turn the returned webhook ID into a full URL: `/api/webhook/`. This will be the only url that we will need for all our interactions. The webhook endpoint will not require authenticated requests. - -## Short note on instance URLs - -Some users have configured Home Assistant to be available outside of their home network using a dynamic DNS service. There are some routers that don't support hairpinning / NAT loopback: a device sending data from inside the routers network, via the externally configured DNS service, to Home Asisstant, which also resides inside the local network. - -To work around this, the app will need to record which WiFi is the home network, and use a direct connection when connected to the home WiFi network. - -## Interaction basics - -All interaction will be done by making HTTP POST requests to the webhook url. These requests do not need to contain authentication. - -The payload format depends on the type of interaction, but it all shares a common base: - -```json5 -{ - "type": "", - // other info -} -``` - -If you received a `secret` during registration, you will need to encrypt your message and wrap it in an encrypted message: - -```json5 -{ - "type": "encrypted", - "data": "" -} -``` - -## Update device location - -This message will inform Home Assistant of new location information. - -```json -{ - "type": "update_location", - "gps": [12.34, 56.78], - "gps_accuracy": 120, - "battery": 45, -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `gps` | latlong | Current location as latitude and longitude. -| `gps_accuracy` | int | GPS accurracy in meters. -| `battery` | int | Percentage of battery the device has left. - -## Call a service - -Call a service in Home Assistant. - -```json -{ - "type": "call_service", - "domain": "light", - "service": "turn_on", - "service_data": { - "entity_id": "light.kitchen" - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `domain` | string | The domain of the service -| `service` | string | The service namae -| `service_data` | dict | The data to send to the service - -## Fire an event - -Fire an event in Home Assistant. - -```json -{ - "type": "fire_event", - "event_type": "my_custom_event", - "event_data": { - "something": 50 - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `event_type` | string | Type of the event to fire -| `event_data` | string | Date of the event to fire - -## Render templates - -> This API is very likely to change in an upcoming release. Support to render multiple templates at once will be added. - -Renders a template and returns the result. - -```json -{ - "type": "render_template", - "template": "Hello {{ name }}, you are {{ states('person.paulus') }}.", - "variables": { - "name": "Paulus" - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `template` | string | The template to render -| `variables` | Dict | The extra template variables to include. - -## Update registration - -Update your app registration. Use this if the app version changed or any of the other values. - -```json -{ - "type": "update_registration", - "app_data": { - "push_notification_key": "abcd" - }, - "app_version": "2.0.0", - "device_name": "Robbies iPhone", - "manufacturer": "Apple, Inc.", - "model": "iPhone XR", - "os_version": "23.02", -} -``` - -All keys are optional. - -| Key | Type | Description -| --- | --- | -- -| `app_version` | string | Version of the mobile app. -| `device_name` | string | Name of the device running the app. -| `manufacturer` | string | The manufacturer of the device running the app. -| `model` | string | The model of the device running the app. -| `os_version` | string | The OS version of the device running the app. -| `app_data` | Dict | App data can be used if the app has a supporting component that extends mobile_app functionality. diff --git a/website/versioned_docs/version-0.89.0/app_integration_setup.md b/website/versioned_docs/version-0.89.0/app_integration_setup.md deleted file mode 100644 index b58b0e13..00000000 --- a/website/versioned_docs/version-0.89.0/app_integration_setup.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Connecting to an instance -id: version-0.89.0-app_integration_setup -original_id: app_integration_setup ---- - -When a user first opens the app, they will need to connect to their local instance to authenticate and register the device. - -## Authenticating the user - -The local instance can be discovered if Home Assistant has the [zeroconf component] configured by searching for `_home-assistant._tcp.local.`. If not configured, the user will need to be asked for the local address of their instance. - -When the address of the instance is known, the app will ask the user to authenticate via [OAuth2 with Home Assistant]. Home Assistant uses IndieAuth, which means that to be able to redirect to a url that triggers your app, you need to take some extra steps. Make sure to read the last paragraph of the "Clients" section thoroughly. - -[zeroconf component]: https://www.home-assistant.io/components/zeroconf -[OAuth2 with Home Assistant]: auth_api.md - -## Registering the device - -> This is an experimental feature. We expect to evolve the API in the upcoming releases. - -_This requires Home Assistant 0.89 or later._ - -Home Assistant has a `mobile_app` component that allows applications to register themselves and interact with the instance. This is a generic component to handle most common mobile application tasks. This component is extendable with custom interactions if your app needs more types of interactions than are offered by this component. - -Once you have tokens to authenticate as a user, it's time to register the app with the mobile app component in Home Assistant. You can do so by making an authenticated POST request to `/api/mobile_app/devices`. [More info on making authenticated requests.](auth_api.md#making-authenticated-requests) - -If you get a 404 when making this request, it means the user does not have the mobile_app component enabled. Prompt the user to enable the `mobile_app` component. The mobile_app component is set up as part of the default Home Assistant configuration. - -Example payload to send to the registration endpoint: - -```json -{ - "app_id": "awesome_home", - "app_name": "Awesome Home", - "app_version": "1.2.0", - "device_name": "Robbies iPhone", - "manufacturer": "Apple, Inc.", - "model": "iPhone X", - "os_version": "iOS 10.12", - "supports_encryption": true, - "app_data": { - "push_notification_key": "abcdef", - } -} -``` - -| Key | Required | Type | Description | -| --- | -------- | ---- | ----------- | -| `app_id` | V | string | A unique identifier for this app. -| `app_name` | V | string | Name of the mobile app. -| `app_version` | V | string | Version of the mobile app. -| `device_name` | V | string | Name of the device running the app. -| `manufacturer` | V | string | The manufacturer of the device running the app. -| `model` | V | string | The model of the device running the app. -| `os_version` | V | string | The OS version of the device running the app. -| `supports_encryption` | V | bool | If the app supports encryption. See also the [encryption section](#encryption). -| `app_data` | | Dict | App data can be used if the app has a supporting component that extends mobile_app functionality. - -When you get a 200 response, the mobile app is registered with Home Assistant. The response is a JSON document and will contain the urls on how to interact with the Home Assistant instance. Store this information. - -```json -{ - "webhook_id": "abcdefgh", - "secret": "qwerty" -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `webhook_id` | string | The webhook ID that can be used to send data back. -| `secret` | string | The secret to use for encrypted communication. Will only be included if encryption is supported by both the app and the Home Assistant instance. - - -## Encryption - -The mobile app component supports encryption to make sure all communication between the app and Home Assistant is encrypted. The encryption is powered by [libsodium](https://libsodium.gitbook.io). Example to encrypt the message using libsodium on Python: - -```python -from nacl.secret import SecretBox -from nacl.encoding import Base64Encoder - -data = SecretBox(key).encrypt( - payload, - encoder=Base64Encoder -).decode("utf-8") -``` diff --git a/website/versioned_docs/version-0.89.0/auth_auth_module.md b/website/versioned_docs/version-0.89.0/auth_auth_module.md deleted file mode 100644 index 68bce3f4..00000000 --- a/website/versioned_docs/version-0.89.0/auth_auth_module.md +++ /dev/null @@ -1,65 +0,0 @@ ---- -title: Multi-factor Authentication Modules -id: version-0.89.0-auth_auth_module -original_id: auth_auth_module ---- - -Multi-factor Authentication Modules are used in conjunction with [Authentication Provider](auth_auth_provider.html) to provide a fully configurable authentication framework. Each MFA module may provide one multi-factor authentication function. User can enable multiple mfa modules, but can only select one module in login process. - -## Defining an mfa auth module - -> We currently only support built-in mfa auth modules. Support for custom auth modules might arrive in the future. - -Multi-factor Auth modules are defined in `homeassistant/auth/mfa_modules/.py`. The auth module will need to provide an implementation of the `MultiFactorAuthModule` class. - -For an example of a fully implemented auth module, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/mfa_modules/insecure_example.py). - -Multi-factor Auth modules shall extend the following methods of `MultiFactorAuthModule` class. - -| method | Required | Description -| ------ | -------- | ----------- -| `@property def input_schema(self)` | Yes | Return a schema defined the user input form. -| `async def async_setup_flow(self, user_id)` | Yes | Return a SetupFlow to handle the setup workflow. -| `async def async_setup_user(self, user_id, setup_data)` | Yes | Set up user for use this auth module. -| `async def async_depose_user(self, user_id)` | Yes | Remove user information from this auth module. -| `async def async_is_user_setup(self, user_id)` | Yes | Return whether user is set up. -| `async def async_validate(self, user_id, user_input)` | Yes | Given a user_id and user input, return validation result. -| `async def async_initialize_login_mfa_step(self, user_id)` | No | Will be called once before display the mfa step of login flow. This is not initialization for the MFA module but the mfa step in login flow. - -## Setup Flow - -Before user can use a multi-factor auth module, it has to be enabled or set up. All available modules will be listed in user profile page, user can enable the module he/she wants to use. A setup data entry flow will guide user finish the necessary steps. - -Each MFA module need to implement a setup flow handler extends from `mfa_modules.SetupFlow` (if only one simple setup step need, `SetupFlow` can be used as well). For example for Google Authenticator (TOTP, Time-based One Time Password) module, the flow will need to be: -- Generate a secret and store it on instance of setup flow -- Return `async_show_form` with a QR code in the description (injected as base64 via `description_placeholders`) -- User scans code and enters a code to verify it scanned correctly and clock in synced -- TOTP module saved the secret along with user_id, module is enabled for user - -## Workflow - -> TODO: draw a diagram - -User == select auth provider ==> LoginFlow.init == input/validate username/password ==> LoginFlow.finish ==> if user enabled mfa ==> LoginFlow.select_mfa_module ==> initialize(optional) ==> LoginFlow.mfa == input/validate MFA code ==> LoginFlow.finish ==> Done - -## Configuration example - -```yaml -# configuration.xml -homeassistant: - auth_providers: - - type: homeassistant - - type: legacy_api_password - auth_mfa_modules: - - type: totp - - type: insecure_example - users: [{'user_id': 'a_32_bytes_length_user_id', 'pin': '123456'}] -``` - -In this example, user will first select from `homeassistant` or `legacy_api_password` auth provider. For `homeassistant` auth provider, user will first input username/password, if that user enabled both `totp` and `insecure_example`, then user need select one auth module, then input Google Authenticator code or input pin code base on the selection. - -> insecure_example is only for demo purpose, please do not use it in production. - -## Validation session - -Not like auth provider, auth module use session to manage the validation. After auth provider validated, mfa module will create a validation session, include an experiation time and user_id from auth provider validate result. Mutli-factor auth module will not only verify the user input, but also verify the session is not expired. The validation session data is stored in your configuration directory. diff --git a/website/versioned_docs/version-0.89.0/config_entries_index.md b/website/versioned_docs/version-0.89.0/config_entries_index.md deleted file mode 100644 index d969b068..00000000 --- a/website/versioned_docs/version-0.89.0/config_entries_index.md +++ /dev/null @@ -1,127 +0,0 @@ ---- -title: Config Entries -sidebar_label: Introduction -id: version-0.89.0-config_entries_index -original_id: config_entries_index ---- - -Config Entries are configuration data that are persistently stored by Home Assistant. A config entry is created by a user via the UI. The UI flow is powered by a [config flow handler](config_entries_config_flow_handler.md) as defined by the component. Config entries can also have an extra [options flow handler](config_entries_options_flow_handler.md), also defined by the component. - -## Lifeceycle - -| State | Description | -| ----- | ----------- | -| not loaded | The config entry has not been loaded. This is the initial state when a config entry is created or when Home Assistant is restarted. | -| loaded | The config entry has been loaded. | -| setup error | An error occurred when trying to set up the config entry. | -| setup retry | A dependency of the config entry was not ready yet. Home Assistant will automatically retry loading this config entry in the future. Time between attempts will automatically increase. -| migration error | The config entry had to be migrated to a newer version, but the migration failed. -| failed unload | The config entry was attempted to be unloaded, but this was either not supported or it raised an exception. - - - -G - -not loaded - -not loaded - -loaded - -loaded - -not loaded->loaded - - - -setup error - -setup error - -not loaded->setup error - - - -setup retry - -setup retry - -not loaded->setup retry - - - -migration error - -migration error - -not loaded->migration error - - - -loaded->not loaded - - - -failed unload - -failed unload - -loaded->failed unload - - - -setup error->not loaded - - - -setup retry->not loaded - - - - - - - - -## Setting up an entry - -During startup, Home Assistant first calls the [normal component setup](https://developers.home-assistant.io/docs/en/creating_component_index.html), -and then call the method `async_setup_entry(hass, entry)` for each entry. If a new Config Entry is -created at runtime, Home Assistant will also call `async_setup_entry(hass, entry)` ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L119)). - -#### For platforms - -If a component includes platforms, it will need to forward the Config Entry to the platform. This can -be done by calling the forward function on the config entry manager ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/bridge.py#L81)): - -```python -# Use `hass.async_add_job` to avoid a circular dependency between the platform and the component -hass.async_add_job(hass.config_entries.async_forward_entry_setup(config_entry, 'light')) -``` - -For a platform to support config entries, it will need to add a setup entry method ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/light/hue.py#L60)): - -```python -async def async_setup_entry(hass, config_entry, async_add_devices): -``` - -## Unloading entries - -Components can optionally support unloading a config entry. When unloading an entry, the component needs -to clean up all entities, unsubscribe any event listener and close all connections. To implement this, -add `async_unload_entry(hass, entry)` to your component ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L136)). - -Platforms will not need to add any logic for unloading a config entry. The entity component will take care of this. -If you need to clean up resources used for an entity, implement the `async_will_remove_from_hass` method on the Entity ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/media_player/cast.py#L313)). diff --git a/website/versioned_docs/version-0.89.0/config_entries_options_flow_handler.md b/website/versioned_docs/version-0.89.0/config_entries_options_flow_handler.md deleted file mode 100644 index a0c51f52..00000000 --- a/website/versioned_docs/version-0.89.0/config_entries_options_flow_handler.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Options Flow Handlers -id: version-0.89.0-config_entries_options_flow_handler -original_id: config_entries_options_flow_handler ---- - -Config Entry Options uses the [Data Flow Entry framework](data_entry_flow_index.md) to allow users to update a config entries options. Components that want to support config entry options will need to define a Options Flow Handler. - -## Options support - -For a component to support options it needs to have an `async_get_options_flow` method in its config flow handler. Calling it will return an instance of the components options flow handler. - -```python -@staticmethod -@callback -def async_get_options_flow(config, options): - return OptionsFlowHandler(config, options) -``` - -## Flow handler - -The Flow handler works just like the config flow handler, except that the first step in the flow will always be `async_step_init`. - -```python -class OptionsFlowHandler(data_entry_flow.FlowHandler): - def __init__(self, config, options): -``` - -## Signal updates - -If the component should act on updated options, you can register an update listener to the config entry that will be called when the entry is updated. - -```python -entry.add_update_listener(update_listener) -``` - -The Listener shall be an async function that takes the same input as async_setup_entry. Options can then be accessed from `entry.options`. - -```python -async def update_listener(hass, entry): -``` - diff --git a/website/versioned_docs/version-0.89.0/creating_component_code_review.md b/website/versioned_docs/version-0.89.0/creating_component_code_review.md deleted file mode 100644 index 8f346eed..00000000 --- a/website/versioned_docs/version-0.89.0/creating_component_code_review.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -title: Checklist for creating a component -id: version-0.89.0-creating_component_code_review -original_id: creating_component_code_review ---- - -A checklist of things to do when you're adding a new component. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on components level - -### 1. Requirements - - 1. Requirement version pinned: `REQUIREMENTS = ['phue==0.8.1']` - 2. We no longer want requirements hosted on GitHub. Please upload to PyPi. - 3. Requirements should [only be imported inside functions](creating_component_deps_and_reqs.md). This is necessary because requirements are installed on the fly. - -### 2. Configuration - - 1. Voluptuous schema present for [configuration validation](development_validation.md) - 2. Default parameters specified in voluptuous schema, not in `setup(…)` - 3. Schema using as many generic config keys as possible from `homeassistant.const` - 4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`. - 5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation` - 6. Never depend on users adding things to `customize` to configure behavior inside your component. - -### 3. Component/platform communication - - 1. If you need to share global data with platforms, use the dictionary `hass.data`. `hass.data[DATA_XY]` while `XY` is the component is preferred over `hass.data[DOMAIN]`. - 2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`. - - -### 4. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - -```python -# bad -status = requests.get(url('/status')) - -# good -from phue import Bridge -bridge = Bridge(...) -status = bridge.status() -``` - -### 5. Limit platforms included in initial pull request -Large pull requests mean there is a larger chance of finding problems that need to be addressed, and more code that needs to be reviewed between every requested change. If your new component will have multiple platforms, try and limit your initial pull request to a single platform. Once the initial component is merged, you can submit additional PRs for the remaining platforms. This allows reviewers to sign off on smaller chunks of code one at a time, and lets us get your new feature in sooner. Pull requests containing large code dumps will not be a priority for review. - -### 6. Event names -Prefix component event names with component name itself. For example, use `xiaomi_aqara.click` instead of `click` for the `xiaomi_aqara` component. diff --git a/website/versioned_docs/version-0.89.0/creating_platform_code_review.md b/website/versioned_docs/version-0.89.0/creating_platform_code_review.md deleted file mode 100644 index 9a3bfc78..00000000 --- a/website/versioned_docs/version-0.89.0/creating_platform_code_review.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: Checklist for creating a platform -id: version-0.89.0-creating_platform_code_review -original_id: creating_platform_code_review ---- - -A checklist of things to do when you're adding a new platform. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on platform level - * Use `CONF_MONITORED_CONDITIONS` instead of `CONF_MONITORED_VARIABLES` - -### 1. Requirements - - 1. Requirement version should be pinned: `REQUIREMENTS = ['phue==0.8.1']` - 2. We no longer want requirements hosted on GitHub. Please upload to PyPi. - 3. Requirements should [only be imported inside functions](creating_component_deps_and_reqs.md). This is necessary because requirements are installed on the fly. - -### 2. Dependencies - - 1. If you depend on a component for the connection, add it to your dependencies: `DEPENDENCIES = ['nest']` - -### 3. Configuration - - 1. Voluptuous schema present for [configuration validation](development_validation.md) - 2. Voluptuous schema extends schema from component
(e.g., `light.hue.PLATFORM_SCHEMA` extends `light.PLATFORM_SCHEMA`) - 3. Default parameters specified in voluptuous schema, not in `setup_platform(...)` - 4. Your `PLATFORM_SCHEMA` should use as many generic config keys as possible from `homeassistant.const` - ```python - import voluptuous as vol - - from homeassistant.const import CONF_FILENAME, CONF_HOST - from homeassistant.components.light import PLATFORM_SCHEMA - import homeassistant.helpers.config_validation as cv - - CONF_ALLOW_UNREACHABLE = 'allow_unreachable' - DEFAULT_UNREACHABLE = False - - PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_ALLOW_UNREACHABLE, - default=DEFAULT_UNREACHABLE): cv.boolean, - vol.Optional(CONF_FILENAME): cv.string, - }) - ``` - 5. Never depend on users adding things to `customize` to configure behavior inside your platform. - -### 4. Setup Platform - - 1. Test if passed in info (user/pass/host etc.) works. - 2. Group your calls to `add_devices` if possible. - 3. If platform adds extra services, format should be `._`. - -### 5. Entity - - 1. Extend entity from component, e.g., `class HueLight(Light)`. - 2. Avoid passing in `hass` as a parameter to the entity. When the entity has been added to Home Assistant, `hass` will be set on the entity by the helper in entity_platform.py. This means you can access `hass` as `self.hass` inside the entity. - 3. Do not call `update()` in constructor, use `add_entities(devices, True)` instead. - 4. Do not do any I/O inside properties. Cache values inside `update()` instead. - 5. The state and/or attributes should not contain relative time since something happened. Instead it should store UTC timestamps. - -### 6. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - -```python -# bad -status = requests.get(url('/status')) - -# good -from phue import Bridge -bridge = Bridge(...) -status = bridge.status() -``` diff --git a/website/versioned_docs/version-0.89.0/development_checklist.md b/website/versioned_docs/version-0.89.0/development_checklist.md deleted file mode 100644 index de28727f..00000000 --- a/website/versioned_docs/version-0.89.0/development_checklist.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -title: Development Checklist -id: version-0.89.0-development_checklist -original_id: development_checklist ---- - - -Before you commit any changes, check your work against these requirements: - -- All communication to external devices or services must be wrapped in an external Python library hosted on [pypi](https://pypi.python.org/pypi). -- All dependencies from [pypi](https://pypi.python.org/pypi) are included via the `REQUIREMENTS` variable in your platform or component and [only imported inside functions](creating_component_deps_and_reqs.md) that use them -- New dependencies are added to `requirements_all.txt` (if applicable), using `script/gen_requirements_all.py` -- The `.coveragerc` file is updated to exclude your platform if there are no tests available or your new code uses a third-party library for communication with the device, service, or sensor -- Documentation is developed for [home-assistant.io](/) - * It's OK to start with adding a docstring with configuration details (for example, sample entry for `configuration.yaml` file) to the file header. Visit the [website documentation](https://www.home-assistant.io/developers/documentation/) for more information about contributing to [home-assistant.io](https://github.com/home-assistant/home-assistant.github.io). diff --git a/website/versioned_docs/version-0.89.0/development_environment.md b/website/versioned_docs/version-0.89.0/development_environment.md deleted file mode 100644 index b70af9af..00000000 --- a/website/versioned_docs/version-0.89.0/development_environment.md +++ /dev/null @@ -1,112 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.89.0-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example CentOS would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Due to Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run - -```bash -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is set up, perform install as for Linux. - -```bash -$ sudo apt-get update -$ sudo apt-get install python3-pip python3-dev python3-venv -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```bash -$ mkdir -p ../config -$ hass -c ../config -``` - -### Developing on OS X - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 autoconf -``` - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv venv -$ source venv/bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```bash -$ hass -``` - -## Logging - -By default logging in Home Assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` diff --git a/website/versioned_docs/version-0.89.0/device_registry_index.md b/website/versioned_docs/version-0.89.0/device_registry_index.md deleted file mode 100644 index ad105683..00000000 --- a/website/versioned_docs/version-0.89.0/device_registry_index.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Device Registry -sidebar_label: Introduction -id: version-0.89.0-device_registry_index -original_id: device_registry_index ---- - -The device registry is a registry where Home Assistant keeps track of devices. A device is represented in Home Assistant via one or more entities. For example, a battery-powered temperature and a humidity sensor might expose entities for temperature, humidity and battery level. - -Device registry overview - -## What is a device? - -A device in Home Assistant represents a physical device that has its own control unit. The control unit itself does not have to be smart, but it should be in control of what happens. For example, an Ecobee thermostat with 4 room sensors equals 5 devices in Home Assistant, one for the thermostat including all sensors inside it, and one for each sensor. - -If you connect a sensor to another device to read some of its data, it should still be represented as two different devices. The reason for this is that the sensor could be moved to read the data of another device. - -> Although not currently available, we could consider offering an option to users to merge devices. - -## Device properties - -| Attribute | Description | -| --------- | ----------- | -| id | Unique ID of device (generated by Home Assistant) -| name | Name of this device -| connections | A set of tuples of `(connection_type, connection identifier)`. Connection types are defined in the device registry module. -| identifiers | Set of identifiers. They identify the device in the outside world. An example is a serial number. -| manufacturer | The manufacturer of the device. -| model | The model of the device. -| config_entries | Config entries that are linked to this device. -| sw_version | The firmware version of the device. -| via_hub | Identifier of a device that routes messages between this device and Home Assistant. Examples of such devices are hubs. This is used to show device topology in Home Assistant. -| area_id | The Area which the device is placed in. - -## Defining devices - -> Entity device info is only read if the entity is loaded via a [config entry](config_entries_index.md). - -Each entity is able to define a device via the `device_info` property. This property is read when an entity is added to Home Assistant via a config entry. A device will be be matched up with an existing device via supplied identifiers and connections, like serial numbers or MAC addresses. - -```python -# Inside a platform -class HueLight(LightEntity): - - @property - def device_info(self): - return { - 'identifiers': { - # Serial numbers are unique identifiers within a specific domain - (hue.DOMAIN, self.unique_id) - }, - 'name': self.name, - 'manufacturer': self.light.manufacturername, - 'model': self.light.productname, - 'sw_version': self.light.swversion, - 'via_hub': (hue.DOMAIN, self.api.bridgeid), - } - -``` - -Components are also able to register devices in the case that there are no entities representing them. An example is a hub that communicates with the lights. - -```python -# Inside a component -from homeassistant.helpers import device_registry as dr - -device_registry = await dr.async_get_registry(hass) - -device_registry.async_get_or_create( - config_entry=entry.entry_id, - connections={ - (dr.CONNECTION_NETWORK_MAC, config.mac) - }, - identifiers={ - (DOMAIN, config.bridgeid) - }, - manufacturer='Signify', - name=config.name, - model=config.modelid, - sw_version=config.swversion, -) -``` diff --git a/website/versioned_docs/version-0.89.0/entity_alarm_control_panel.md b/website/versioned_docs/version-0.89.0/entity_alarm_control_panel.md deleted file mode 100644 index afd030d6..00000000 --- a/website/versioned_docs/version-0.89.0/entity_alarm_control_panel.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Alarm Control Panel Entity -sidebar_label: Alarm Control Panel -id: version-0.89.0-entity_alarm_control_panel -original_id: entity_alarm_control_panel ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| state | string | **Required** | One of the states listed in the **states** section. -| code_format | string | `None` | One of the states listed in the **code formats** section. -| changed_by | string | `None` | Last change triggered by. - - -### States - -| Value | Description -| ----- | ----------- -| `disarmed` | The alarm is disarmed (`off`). -| `armed_home` | The alarm is armed in home mode. -| `armed_away` | The alarm is armed in away mode. -| `armed_night` | The alarm is armed in night mode. -| `armed_custom_bypass` | The alarm is armed in bypass mode. -| `pending` | The alarm is pending (towards `triggered`). -| `arming` | The alarm is arming. -| `disarming` | The alarm is disarming. -| `triggered` | The alarm is triggered. - - -### Code Formats - -| Value | Description -| ----- | ----------- -| None | No code required. -| Number | Code is a number (Shows ten-key pad on frontend). -| Any | Code is a string. - - -## Methods - -### Alarm Disarm -Send disarm command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_disarm(self, code=None) -> None: - """Send disarm command.""" - - async def async_alarm_disarm(self, code=None) -> None: - """Send disarm command.""" -``` - -### Alarm Arm Home -Send arm home command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_home(self, code=None) -> None: - """Send arm home command.""" - - def async_alarm_arm_home(self, code=None) -> None: - """Send arm home command.""" -``` - -### Alarm Arm Away -Send arm away command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_away(self, code=None) -> None: - """Send arm away command.""" - - def async_alarm_arm_away(self, code=None) -> None: - """Send arm away command.""" -``` - -### Alarm Arm Night -Send arm night command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_night(self, code=None) -> None: - """Send arm night command.""" - - def async_alarm_arm_night(self, code=None) -> None: - """Send arm night command.""" -``` - -### Alarm Trigger -Send alarm trigger command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_trigger(self, code=None) -> None: - """Send alarm trigger command.""" - - def async_alarm_trigger(self, code=None) -> None: - """Send alarm trigger command.""" -``` - -### Alarm Custom Bypass -Send arm custom bypass command. - -```python -class MyAlarm(AlarmControlPanel): - # Implement one of these methods. - - def alarm_arm_custom_bypass(self, code=None) -> None: - """Send arm custom bypass command.""" - - def async_alarm_arm_custom_bypass(self, code=None) -> None: - """Send arm custom bypass command.""" -``` diff --git a/website/versioned_docs/version-0.89.0/entity_cover.md b/website/versioned_docs/version-0.89.0/entity_cover.md deleted file mode 100644 index 8ef25929..00000000 --- a/website/versioned_docs/version-0.89.0/entity_cover.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -title: Cover Entity -sidebar_label: Cover -id: version-0.89.0-entity_cover -original_id: entity_cover ---- - -A cover entity is a device that controls an opening or cover, such as a garage door and window shade. Derive entity platforms from [`homeassistant.components.cover.CoverDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/cover/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -### Platform Properties (to be implemented by deriving platform classes) - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| current_cover_position | int | None | The current position of cover where 0 means closed and 100 is fully open. Required with `SUPPORT_SET_POSITION`. -| current_cover_tilt_position | int | None | The current tilt position of the cover where 0 means closed/no tilt and 100 means open/maximum tilt. Required with `SUPPORT_SET_TILT_POSITION` -| is_opening | bool | None | If the cover is opening or not. Used to determine `state`. -| is_closing | bool | None | If the cover is closing or not. Used to determine `state`. -| is_closed | bool | `NotImplementedError()` | If the cover is closed or not. if the state is unknown, return `None`. Used to determine `state`. - -### Entity Properties (base class properties which may be overriden) - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| device_class | string | None | Describes the type/class of the cover. Must be `None` or one of the valid values from the table below. -| supported_features | int (bitwise) | Value determined from `current_cover_position` and `current_cover_tilt_position` | Describes the supported features. See the related table below for details. - -### Device Classes -| Constant | Description -|----------|-----------------------| -| `DEVICE_CLASS_AWNING` | Control of an awning, such as an exterior retractible window, door, or patio cover. -| `DEVICE_CLASS_BLIND` | Control of blinds, which are linked slats that expand or collapse to cover an opening or may be tilted to partially cover an opening, such as window blinds. -| `DEVICE_CLASS_CURTAIN` | Control of curtains or drapes, which is often fabric hung above a window or door that can be drawn open. -| `DEVICE_CLASS_DAMPER` | Control of a mechanical damper that reduces air flow, sound, or light. -| `DEVICE_CLASS_DOOR` | Control of a door or gate that provides access to an area. -| `DEVICE_CLASS_GARAGE` | Control of a garage door that provides access to a garage. -| `DEVICE_CLASS_SHADE` | Control of shades, which are a continous plane of material or connected cells that expanded or collapsed over an opening, such as window shades. -| `DEVICE_CLASS_SHUTTER` | Control of shutters, which are linked slats that swing out/in to cover an opening or may be tilted to partially cover an opening, such as indoor or exterior window shutters. -| `DEVICE_CLASS_WINDOW` | Control of a physical window that opens and closes or may tilt. - -### States -| Constant | Description -|----------|------------------------| -| `STATE_OPENING` | The cover is in the process of opening to reach a set position. -| `STATE_OPEN` | The cover has reached the open position. -| `STATE_CLOSING` | The cover is in the process of closing to reach a set position. -| `STATE_CLOSED` | The cover has reach the closed position. - - -### Supported Features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Constant | Description | -|----------|--------------------------------------| -| `SUPPORT_OPEN` | The cover supports being opened. -| `SUPPORT_CLOSE` | The cover supports being closed. -| `SUPPORT_SET_POSITION` | The cover supports moving to a specific position between opened and closed. -| `SUPPORT_STOP` | The cover supports stopping the current action (open, close, set position) -| `SUPPORT_OPEN_TILT` | The cover supports being tilting open. -| `SUPPORT_CLOSE_TILT` | The cover supports being tilting closed. -| `SUPPORT_SET_TILT_POSITION` | The cover supports moving to a specific tilt position between opened and closed. -| `SUPPORT_STOP_TILT` | The cover supports stopping the current tilt action (open, close, set position) - -## Methods - -### Open cover - -Only implement this method if the flag `SUPPORT_CLOSE` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover(self, **kwargs): - """Open the cover.""" - - async def async_open_cover(self, **kwargs): - """Open the cover.""" -``` - -### Close cover - -Only implement this method if the flag `SUPPORT_CLOSE` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover(self, **kwargs): - """Close cover.""" - - async def async_close_cover(self, **kwargs): - """Close cover.""" -``` - -### Set cover position - -Only implement this method if the flag `SUPPORT_SET_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" - - async def async_set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" - -``` - -### Stop cover - -Only implement this metohd if the flag `SUPPORT_STOP` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover(self, **kwargs): - """Stop the cover.""" -``` - -### Open cover tilt - -Only implement this method if the flag `SUPPORT_OPEN_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" - - async def async_open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" -``` - -### Close cover tilt - -Only implement this method if the flag `SUPPORT_CLOSE_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" - - async def async_close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" -``` - -### Set cover tilt position - -Only implement this method if the flag `SUPPORT_SET_TILT_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" - - async def async_set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" -``` - -### Stop cover tilt - -Only implement this method if the flag `SUPPORT_STOP_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover_tilt(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover_tilt(self, **kwargs): - """Stop the cover.""" -``` \ No newline at end of file diff --git a/website/versioned_docs/version-0.89.0/internationalization_translation.md b/website/versioned_docs/version-0.89.0/internationalization_translation.md deleted file mode 100644 index 1aa4cb15..00000000 --- a/website/versioned_docs/version-0.89.0/internationalization_translation.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Translation -id: version-0.89.0-internationalization_translation -original_id: internationalization_translation ---- - -## How to start -Translations for Home Assistant are managed through Lokalise, an online translation management tool. Our translations are split between two projects, a backend project for platform-specific translations, and a frontend project for UI translations. Click the links below to join both projects! Even if your language is completely translated, extra proofreading is a big help! Please feel free to review the existing translations, and vote for alternatives that might be more appropriate. - -- [Join the frontend translation team](https://lokalise.co/signup/3420425759f6d6d241f598.13594006/all/) -- [Join the backend translation team](https://lokalise.co/signup/130246255a974bd3b5e8a1.51616605/all/) -- [Join the iOS translation team](https://lokalise.co/signup/834452985a05254348aee2.46389241/all/) - -For more information about the translation workflow, please see the [Lokalise translation workflow documents](https://docs.lokalise.co/category/iOzEuQPS53-for-team-leads-and-translators). - -> The translation of the Home Assistant frontend is still a work in progress. More phrases will be available for translation soon. - -## Translation placeholders - -Some translation strings will contain special placeholders that will be replaced later. Placeholders shown in square brackets `[]` are [Lokalise key references](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing). These are primarily used to link translation strings that will be duplicated. Different languages may not have the same duplicates as English, and are welcome to link duplicate translations that are not linked in English. Placeholders shown in curly brackets `{}` are [translation arguments](https://formatjs.io/guides/message-syntax/) that will be replaced with a live value when Home Assistant is running. Any translation argument placeholders present in the original string must be included in the translated string. These may include special syntax for defining plurals or other replacement rules. The linked format.js guide explains the syntax for adding plural definitions and other rules. - -## Rules -1. Only native speakers should submit translations. -2. Stick to [Material Design guidelines](https://material.io/guidelines/style/writing.html). -3. Don't translate or change proper nouns like `Home Assistant`, `Hass.io` or `Hue`. -4. For a region specific translation, keys that will be the same as the base translation should be filled with `[VOID]`. These will be replaced during our translation build process. -5. Translations under the `state_badge` keys will be used for the notification badge display. These translations should be short enough to fit in the badge label without overflowing. This can be tested in the Home Assistant UI either by editing the label text with your browsers development tools, or by using the States states dev tool icon developer tool in the Home Assistant UI. In the UI, enter a new entity ID (`device_tracker.test`), and enter the text you want to test in state. -6. If text will be duplicated across different translation keys, make use of the Lokalise key reference feature where possible. The base translation provides examples of this underneath the `states` translations. Please see the [Lokalise key referencing](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing) documentation for more details. - -## Adding a new language -If your language is not listed you can request it at [GitHub](https://github.com/home-assistant/home-assistant-polymer/issues/new). Please provide both the English name and the native name for your language. For example: -``` -English Name: German -Native Name: Deutsch -``` - -> Region specific translations (`en-US`, `fr-CA`) will only be included if translations for that region need to differ from the base language translation. - -### Maintainer steps to add a new language -1. Language tags have to follow [BCP 47](https://tools.ietf.org/html/bcp47). A list of most language tags can be found here: [IANA sutbtag registry](http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry). Examples: `fr`, `fr-CA`, `zh-Hans`. Only include the country code if country specific overrides are being included, and the base language is already translated. -2. Add the language tag and native name in `src/translations/translationMetadata.json`. Examples: "Français", "Français (CA)" -3. Add the new language in Lokalize. -Note: Sometimes you have to change the tag in Lokalise (Language -> Language settings -> custom ISO code). diff --git a/website/versioned_docs/version-0.90.0/app_integration_sending_data.md b/website/versioned_docs/version-0.90.0/app_integration_sending_data.md deleted file mode 100644 index 8593aee9..00000000 --- a/website/versioned_docs/version-0.90.0/app_integration_sending_data.md +++ /dev/null @@ -1,146 +0,0 @@ ---- -title: Sending data home -id: version-0.90.0-app_integration_sending_data -original_id: app_integration_sending_data ---- - -Once you have registered your app with the mobile app component, you can start interacting with Home Assistant via the provided webhook information. - -The first step is to turn the returned webhook ID into a full URL: `/api/webhook/`. This will be the only url that we will need for all our interactions. The webhook endpoint will not require authenticated requests. - -## Short note on instance URLs - -Some users have configured Home Assistant to be available outside of their home network using a dynamic DNS service. There are some routers that don't support hairpinning / NAT loopback: a device sending data from inside the routers network, via the externally configured DNS service, to Home Asisstant, which also resides inside the local network. - -To work around this, the app will need to record which WiFi is the home network, and use a direct connection when connected to the home WiFi network. - -## Interaction basics - -All interaction will be done by making HTTP POST requests to the webhook url. These requests do not need to contain authentication. - -The payload format depends on the type of interaction, but it all shares a common base: - -```json5 -{ - "type": "", - // other info -} -``` - -If you received a `secret` during registration, you will need to encrypt your message and wrap it in an encrypted message: - -```json5 -{ - "type": "encrypted", - "data": "" -} -``` - -## Update device location - -This message will inform Home Assistant of new location information. - -```json -{ - "type": "update_location", - "gps": [12.34, 56.78], - "gps_accuracy": 120, - "battery": 45, -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `gps` | latlong | Current location as latitude and longitude. -| `gps_accuracy` | int | GPS accurracy in meters. -| `battery` | int | Percentage of battery the device has left. - -## Call a service - -Call a service in Home Assistant. - -```json -{ - "type": "call_service", - "domain": "light", - "service": "turn_on", - "service_data": { - "entity_id": "light.kitchen" - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `domain` | string | The domain of the service -| `service` | string | The service name -| `service_data` | dict | The data to send to the service - -## Fire an event - -Fire an event in Home Assistant. - -```json -{ - "type": "fire_event", - "event_type": "my_custom_event", - "event_data": { - "something": 50 - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `event_type` | string | Type of the event to fire -| `event_data` | string | Date of the event to fire - -## Render templates - -> This API is very likely to change in an upcoming release. Support to render multiple templates at once will be added. - -Renders a template and returns the result. - -```json -{ - "type": "render_template", - "template": "Hello {{ name }}, you are {{ states('person.paulus') }}.", - "variables": { - "name": "Paulus" - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `template` | string | The template to render -| `variables` | Dict | The extra template variables to include. - -## Update registration - -Update your app registration. Use this if the app version changed or any of the other values. - -```json -{ - "type": "update_registration", - "app_data": { - "push_notification_key": "abcd" - }, - "app_version": "2.0.0", - "device_name": "Robbies iPhone", - "manufacturer": "Apple, Inc.", - "model": "iPhone XR", - "os_version": "23.02", -} -``` - -All keys are optional. - -| Key | Type | Description -| --- | --- | -- -| `app_version` | string | Version of the mobile app. -| `device_name` | string | Name of the device running the app. -| `manufacturer` | string | The manufacturer of the device running the app. -| `model` | string | The model of the device running the app. -| `os_version` | string | The OS version of the device running the app. -| `app_data` | Dict | App data can be used if the app has a supporting component that extends mobile_app functionality. diff --git a/website/versioned_docs/version-0.90.0/auth_permissions.md b/website/versioned_docs/version-0.90.0/auth_permissions.md deleted file mode 100644 index 93a56a4e..00000000 --- a/website/versioned_docs/version-0.90.0/auth_permissions.md +++ /dev/null @@ -1,273 +0,0 @@ ---- -title: Permissions -id: version-0.90.0-auth_permissions -original_id: auth_permissions ---- - -> This is an experimental feature that is not enabled or enforced yet - -Permissions limit the things a user has access to or can control. Permissions are attached to groups, of which a user can be a member. The combined permissions of all groups a user is a member of decides what a user can and cannot see or control. - -Permissions do not apply to the user that is flagged as "owner". This user will always have access to everything. - -## General permission structure - -Policies are dictionaries that at the root level consist of different categories of permissions. In the current implementation this is limited to just entities. - -```python -{ - "entities": … -} -``` - -Each category can further split into subcategories that describe parts of that category. - -```python -{ - "entities": { - "domains": …, - "entity_ids": … - } -} -``` - -If a category is omitted, the user will not have permission to that category. - -When defining a policy, any dictionary value at any place can be replaced with `True` or `None`. `True` means that permission is granted and `None` means use default, which is deny access. - -## Entities - -Entity permissions can be set on a per entity and per domain basis using the subcategories `entity_ids`, `device_ids`, `area_ids` and `domains`. You can either grant all access by setting the value to `True`, or you can specify each entity individually using the "read", "control", "edit" permissions. - -The system will return the first matching result, based on the order: `entity_ids`, `device_ids`, `area_ids`, `domains`, `all`. - -```json -{ - "entities": { - "domains": { - "switch": true - }, - "entity_ids": { - "light.kitchen": { - "read": true, - "control": true - } - } - } -} -``` - -## Merging policies - -If a user is a member of multiple groups, the groups permission policies will be combined into a single policy at runtime. When merging policies, we will look at each level of the dictionary and compare the values for each source using the following methodology: - -1. If any of the values is `True`, the merged value becomes `True`. -2. If any value is a dictionary, the merged value becomes a dictionary created by recursively checking each value using this methodology. -3. If all values are `None`, the merged value becomes `None`. - -Let's look at an example: - -```python -{ - "entities": { - "entity_ids": { - "light.kitchen": True - } - } -} -``` - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -Once merged becomes - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -## Checking permissions - -We currently have two different permission checks: can the user do the read/control/edit operation on an entity, and is the user an admin and thus allowed to change this configuration setting. - -Certain APIs will always be accessible to all users, but might offer a limited scope based on the permissions, like rendering a template. - -### Checking permissions - -To check a permission, you will need to have access to the user object. Once you have the user object, checking the permission is easy. - -```python -from homeassistant.exceptions import Unauthorized -from homeasistant.permissions.const import ( - POLICY_READ, POLICY_CONTROL, POLICY_EDIT -) - -# Raise error if user is not an admin -if not user.is_admin: - raise Unauthorized() - - -# Raise error if user does not have access to control an entity -# Available policies: POLICY_READ, POLICY_CONTROL, POLICY_EDIT -if not user.permissions.check_entity(entity_id, POLICY_CONTROL): - raise Unauthorized() -``` - -### The context object - -All service calls, fired events and states in Home Assistant have a context object. This object allows us to attribute changes to events and services. These context objects also contain a user id, which is used for checking the permissions. - -It's crucial for permission checking that actions taken on behalf of the user are done with a context containing the user ID. If you are in a service handler, you should re-use the incoming context `call.context`. If you are inside a WebSocket API or Rest API endpoint, you should create a context with the correct user: - -```python -from homeassistant.core import Context - -await hass.services.async_call('homeassistant', 'stop', context=Context( - user_id=user.id -), blocking=True) -``` - -### If a permission check fails - -When you detect an anauthorized action, you should raise the `homeassistant.exceptions.Unauthorized` exception. This exception will cancel the current action and notifies the user that their action is unauthorized. - -The `Unauthorized` exception has various parameters, to identify the permission check that failed. All fields are optional. - -| # Not all actions have an ID (like adding config entry) -| # We then use this fallback to know what category was unauth - - -| Parameter | Description -| --------- | ----------- -| context | The context of the current call. -| user_id | The user ID that we tried to operate on. -| entity_id | The entity ID that we tried to operate on. -| config_entry_id | The config entry ID that we tried to operate on. -| perm_category | The permission category that we tested. Only necessary if we don't have an object ID that the user tried to operate on (like when we create a config entry). -| permission | The permission that we tested, ie `POLICY_READ`. - -### Securing a service call handler - -Service calls allow a user to control entities or with the integration as a whole. A service call uses the attached context to see which user invoked the command. Because context is used, it is important that you also pass the call context to all service calls. - -All services that are registered via the entity component (`component.async_register_entity_service()`) will automatically have their permissions checked. - -#### Checking entity permissions - -Your service call handler will need to check the permissions for each entity that it will act on. - -```python -from homeassistant.exceptions import Unauthorized, UnknownUser -from homeassistant.auth.permissions.const import POLICY_CONTROL - -async def handle_entity_service(call): - """Handle a service call.""" - entity_ids = call.data['entity_id'] - - for entity_id in entity_ids: - if call.context.user_id: - user = await hass.auth.async_get_user(call.context.user_id) - - if user is None: - raise UnknownUser( - context=call.context, - entity_id=entity_id, - policy=POLICY_CONTROL, - ) - - if not user.permissions.check_entity(entity_id, POLICY_CONTROL): - raise Unauthorized( - context=call.context, - entity_id=entity_id, - policy=POLICY_CONTROL, - ) - - # Do action on entity - - -async def async_setup(hass, config): - hass.services.async_register(DOMAIN, 'my_service', handle_entity_service) - return True -``` - -#### Checking admin permission - -Starting Home Assistant 0.90, there is a special decorator to help protect -services that require admin access. - -```python -# New in Home Assistant 0.90 -async def handle_admin_service(call): - """Handle a service call.""" - # Do admin action - - -async def async_setup(hass, config): - hass.helpers.service.async_register_admin_service( - DOMAIN, 'my_service', handle_admin_service, vol.Schema({}) - ) - return True -``` - -### Securing a REST API endpoint - -```python -from homeassistant.core import Context -from homeassistant.components.http.view import HomeAssistantView -from homeassistant.exceptions import Unauthorized - - -class MyView(HomeAssistantView): - """View to handle Status requests.""" - - url = '/api/my-component/my-api' - name = 'api:my-component:my-api' - - async def post(self, request): - """Notify that the API is running.""" - hass = request.app['hass'] - user = request['hass_user'] - - if not user.is_admin: - raise Unauthorized() - - hass.bus.async_fire('my-component-api-running', context=Context( - user_id=user.id - )) - - return self.json_message("Done.") -``` - -### Securing a Websocket API endpoint - -Verifying permissions in a Websocket API endpoint can be done by accessing the -user via `connection.user`. If you need to check admin access, you can use the -built-in `@require_admin` decorator. - -```python -from homeassistant.compnents import websocket_api - - -async def async_setup(hass, config): - hass.components.websocket_api.async_register_command(websocket_create) - return True - - -@websocket_api.require_admin -@websocket_api.async_response -@websocket_api.websocket_command({ - vol.Required('type'): 'my-component/my-action', -}) -async def websocket_create(hass, connection, msg): - """Create a user.""" - # Do action -``` diff --git a/website/versioned_docs/version-0.90.0/config_entries_index.md b/website/versioned_docs/version-0.90.0/config_entries_index.md deleted file mode 100644 index 01eac9dc..00000000 --- a/website/versioned_docs/version-0.90.0/config_entries_index.md +++ /dev/null @@ -1,136 +0,0 @@ ---- -title: Config Entries -sidebar_label: Introduction -id: version-0.90.0-config_entries_index -original_id: config_entries_index ---- - -Config Entries are configuration data that are persistently stored by Home Assistant. A config entry is created by a user via the UI. The UI flow is powered by a [config flow handler](config_entries_config_flow_handler.md) as defined by the component. Config entries can also have an extra [options flow handler](config_entries_options_flow_handler.md), also defined by the component. - -## Lifecycle - -| State | Description | -| ----- | ----------- | -| not loaded | The config entry has not been loaded. This is the initial state when a config entry is created or when Home Assistant is restarted. | -| loaded | The config entry has been loaded. | -| setup error | An error occurred when trying to set up the config entry. | -| setup retry | A dependency of the config entry was not ready yet. Home Assistant will automatically retry loading this config entry in the future. Time between attempts will automatically increase. -| migration error | The config entry had to be migrated to a newer version, but the migration failed. -| failed unload | The config entry was attempted to be unloaded, but this was either not supported or it raised an exception. - - - -G - -not loaded - -not loaded - -loaded - -loaded - -not loaded->loaded - - - -setup error - -setup error - -not loaded->setup error - - - -setup retry - -setup retry - -not loaded->setup retry - - - -migration error - -migration error - -not loaded->migration error - - - -loaded->not loaded - - - -failed unload - -failed unload - -loaded->failed unload - - - -setup error->not loaded - - - -setup retry->not loaded - - - - - - - - -## Setting up an entry - -During startup, Home Assistant first calls the [normal component setup](https://developers.home-assistant.io/docs/en/creating_component_index.html), -and then call the method `async_setup_entry(hass, entry)` for each entry. If a new Config Entry is -created at runtime, Home Assistant will also call `async_setup_entry(hass, entry)` ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L119)). - -#### For platforms - -If a component includes platforms, it will need to forward the Config Entry to the platform. This can -be done by calling the forward function on the config entry manager ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/bridge.py#L81)): - -```python -# Use `hass.async_add_job` to avoid a circular dependency between the platform and the component -hass.async_add_job(hass.config_entries.async_forward_entry_setup(config_entry, 'light')) -``` - -For a platform to support config entries, it will need to add a setup entry method ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/light/hue.py#L60)): - -```python -async def async_setup_entry(hass, config_entry, async_add_devices): -``` - -## Unloading entries - -Components can optionally support unloading a config entry. When unloading an entry, the component needs -to clean up all entities, unsubscribe any event listener and close all connections. To implement this, -add `async_unload_entry(hass, entry)` to your component ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L136)). - -Platforms will not need to add any logic for unloading a config entry. The entity component will take care of this. -If you need to clean up resources used for an entity, implement the `async_will_remove_from_hass` method on the Entity ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/media_player/cast.py#L313)). - -## Removal of entries - -If a component needs to clean up code when an entry is removed, it can define a removal method: - -```python -async def async_remove_entry(hass, entry) -> None: - """Handle removal of an entry.""" -``` diff --git a/website/versioned_docs/version-0.90.0/development_environment.md b/website/versioned_docs/version-0.90.0/development_environment.md deleted file mode 100644 index 007a47e4..00000000 --- a/website/versioned_docs/version-0.90.0/development_environment.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.90.0-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example CentOS would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Due to Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run - -```bash -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is set up, perform install as for Linux. - -```bash -$ sudo apt-get update -$ sudo apt-get install python3-pip python3-dev python3-venv -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```bash -$ mkdir -p ../config -$ hass -c ../config -``` - -### Developing on OS X - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 autoconf -``` - -Then install ffmpeg: - -```bash -$ brew install ffmpeg -``` - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv venv -$ source venv/bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```bash -$ hass -``` - -## Logging - -By default logging in Home Assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` diff --git a/website/versioned_docs/version-0.90.0/device_registry_index.md b/website/versioned_docs/version-0.90.0/device_registry_index.md deleted file mode 100644 index a420351e..00000000 --- a/website/versioned_docs/version-0.90.0/device_registry_index.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Device Registry -sidebar_label: Introduction -id: version-0.90.0-device_registry_index -original_id: device_registry_index ---- - -The device registry is a registry where Home Assistant keeps track of devices. A device is represented in Home Assistant via one or more entities. For example, a battery-powered temperature and a humidity sensor might expose entities for temperature, humidity and battery level. - -Device registry overview - -## What is a device? - -A device in Home Assistant represents a physical device that has its own control unit. The control unit itself does not have to be smart, but it should be in control of what happens. For example, an Ecobee thermostat with 4 room sensors equals 5 devices in Home Assistant, one for the thermostat including all sensors inside it, and one for each sensor. - -If you connect a sensor to another device to read some of its data, it should still be represented as two different devices. The reason for this is that the sensor could be moved to read the data of another device. - -> Although not currently available, we could consider offering an option to users to merge devices. - -## Device properties - -| Attribute | Description | -| --------- | ----------- | -| id | Unique ID of device (generated by Home Assistant) -| name | Name of this device -| connections | A set of tuples of `(connection_type, connection identifier)`. Connection types are defined in the device registry module. -| identifiers | Set of identifiers. They identify the device in the outside world. An example is a serial number. -| manufacturer | The manufacturer of the device. -| model | The model of the device. -| config_entries | Config entries that are linked to this device. -| sw_version | The firmware version of the device. -| via_hub | Identifier of a device that routes messages between this device and Home Assistant. Examples of such devices are hubs. This is used to show device topology in Home Assistant. -| area_id | The Area which the device is placed in. - -## Defining devices - -> Entity device info is only read if the entity is loaded via a [config entry](config_entries_index.md). - -Each entity is able to define a device via the `device_info` property. This property is read when an entity is added to Home Assistant via a config entry. A device will be matched up with an existing device via supplied identifiers and connections, like serial numbers or MAC addresses. - -```python -# Inside a platform -class HueLight(LightEntity): - - @property - def device_info(self): - return { - 'identifiers': { - # Serial numbers are unique identifiers within a specific domain - (hue.DOMAIN, self.unique_id) - }, - 'name': self.name, - 'manufacturer': self.light.manufacturername, - 'model': self.light.productname, - 'sw_version': self.light.swversion, - 'via_hub': (hue.DOMAIN, self.api.bridgeid), - } - -``` - -Components are also able to register devices in the case that there are no entities representing them. An example is a hub that communicates with the lights. - -```python -# Inside a component -from homeassistant.helpers import device_registry as dr - -device_registry = await dr.async_get_registry(hass) - -device_registry.async_get_or_create( - config_entry=entry.entry_id, - connections={ - (dr.CONNECTION_NETWORK_MAC, config.mac) - }, - identifiers={ - (DOMAIN, config.bridgeid) - }, - manufacturer='Signify', - name=config.name, - model=config.modelid, - sw_version=config.swversion, -) -``` diff --git a/website/versioned_docs/version-0.90.0/external_api_rest.md b/website/versioned_docs/version-0.90.0/external_api_rest.md deleted file mode 100644 index eea4b2bb..00000000 --- a/website/versioned_docs/version-0.90.0/external_api_rest.md +++ /dev/null @@ -1,530 +0,0 @@ ---- -title: REST API -id: version-0.90.0-external_api_rest -original_id: external_api_rest ---- - -Home Assistant provides a RESTful API on the same port as the web frontend. (default port is port 8123). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -* http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -* http://IP_ADDRESS:8123/api/ is a RESTful API. - -The API accepts and returns only JSON encoded objects. - -All API calls have to be accompanied by the header `Authorization: Bearer ABCDEFGH`, where `ABCDEFGH` is replaced by your token. You can obtain a token ("Long-Lived Access Token") by logging into the frontend using a web browser, and going to [your profile](https://www.home-assistant.io/docs/authentication/#your-account-profile) `http://IP_ADDRESS:8123/profile`. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```bash -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. - -```python -from requests import get - -url = 'http://localhost:8123/ENDPOINT' -headers = { - 'Authorization': 'Bearer ABCDEFGH', - 'content-type': 'application/json', -} - -response = get(url, headers=headers) -print(response.text) -``` -Another option is to use the Restful Command component https://www.home-assistant.io/components/rest_command/ in a Home Assistant automation or script. - -```yaml -turn_light_on: - url: http://localhost:8123/api/states/light.study_light - method: POST - headers: - authorization: 'Bearer ABCDEFGH' - content-type: 'application/json' - payload: '{"state":"on"}' -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on one or more entities - comma separated. -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates the current state of an entity. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance.
- -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` diff --git a/website/versioned_docs/version-0.90.0/external_api_websocket.md b/website/versioned_docs/version-0.90.0/external_api_websocket.md deleted file mode 100644 index 906792ca..00000000 --- a/website/versioned_docs/version-0.90.0/external_api_websocket.md +++ /dev/null @@ -1,436 +0,0 @@ ---- -title: WebSocket API -id: version-0.90.0-external_api_websocket -original_id: external_api_websocket ---- - -Home Assistant contains a WebSocket API. This API can be used to stream information from a Home Assistant instance to any client that implements WebSockets. Implementations in different languages: - -- [JavaScript](https://github.com/home-assistant/home-assistant-js-websocket) - powers the frontend -- [Python](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket-client.py) - CLI client using [`asyncws`](https://async-websockets.readthedocs.io/en/latest/) -- [JavaScript/HTML](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket.html) - WebSocket connection in your browser - -Connect your websocket implementation to `ws://localhost:8123/api/websocket`. You will need a valid access token. - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`websocket_api` component](https://www.home-assistant.io/components/websocket_api/) to your `configuration.yaml` file to use the WebSocket API. - -## Server states - -1. Client connects. -1. Authentication phase starts. - - Server sends `auth_required` message. - - Client sends `auth` message. - - If `auth` message correct: go to 3. - - Server sends `auth_invalid`. Go to 6. -1. Send `auth_ok` message -1. Authentication phase ends. -1. Command phase starts. - 1. Client can send commands. - 1. Server can send results of previous commands. -1. Client or server disconnects session. - -During the command phase, the client attaches a unique identifier to each message. The server will add this identifier to each message so that the client can link each message to its origin. - -## Message format - -Each API message is a JSON serialized object containing a `type` key. After the authentication phase messages also must contain an `id`, an integer that contains the number of interactions. - -Example of an auth message: - -```json -{ - "type": "auth", - "access_token": "ABCDEFGHIJKLMNOPQ" -} -``` - -```json -{ - "id": 5, - "type":"event", - "event":{ - "data":{}, - "event_type":"test_event", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -## Authentication phase - -When a client connects to the server, the server will test if the client is authenticated. Authentication will not be necessary if no api_password is set or if the user fulfills one of the other criteria for authentication (trusted network, password in url/header). - -If no authentication is needed, the authentication phase will complete and the server will send an `auth_ok` message. - -```json -{ - "type": "auth_ok" -} -``` - -If authentication is necessary, the server sends out `auth_required`. - -```json -{ - "type": "auth_required" -} -``` - -This means that the next message from the client should be an auth message. You can authorize with an access token. - -```json -{ - "type": "auth", - "access_token": "ABCDEFGH" -} -``` - -For now, we also support authentication with an API password (legacy auth). - -```json -{ - "type": "auth", - "api_password": "supersecret" -} -``` - -If the client supplies valid authentication, the authentication phase will complete by the server sending the `auth_ok` message: - -```json -{ - "type": "auth_ok" -} -``` - -If the data is incorrect, the server will reply with `auth_invalid` message and disconnect the session. - -```json -{ - "type": "auth_invalid", - "message": "Invalid password" -} -``` - -## Command phase - -During this phase the client can give commands to the server. The server will respond to each command with a `result` message indicating when the command is done and if it was successful. - -```json -{ - "id": 6. - "type": "result", - "success": true, - // Can contain extra result info - "result": null -} -``` - -## Subscribe to events - -The command `subscribe_events` will subscribe your client to the event bus. You can either listen to all events or to a specific event type. If you want to listen to multiple event types, you will have to send multiple `subscribe_events` commands. - -```json -{ - "id": 18, - "type": "subscribe_events", - // Optional - "event_type": "state_changed" -} -``` - -The server will respond with a result message to indicate that the subscription is active. - -```json -{ - "id": 18, - "type": "result", - "success": true, - "result": null -} -``` - -For each event that matches, the server will send a message of type `event`. The `id` in the message will point at the original `id` of the `listen_event` command. - -```json -{ - "id": 18, - "type":"event", - "event":{ - "data":{ - "entity_id":"light.bed_light", - "new_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:24.265390+00:00", - "state":"on", - "attributes":{ - "rgb_color":[ - 254, - 208, - 0 - ], - "color_temp":380, - "supported_features":147, - "xy_color":[ - 0.5, - 0.5 - ], - "brightness":180, - "white_value":200, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:24.265390+00:00" - }, - "old_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:10.466994+00:00", - "state":"off", - "attributes":{ - "supported_features":147, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:10.466994+00:00" - } - }, - "event_type":"state_changed", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -### Unsubscribing from events - -You can unsubscribe from previously created subscription events. Pass the id of the original subscription command as value to the subscription field. - -```json -{ - "id": 19, - "type": "unsubscribe_events", - "subscription": 18 -} -``` - -The server will respond with a result message to indicate that unsubscribing was successful. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": null -} -``` - -### Calling a service - -This will call a service in Home Assistant. Right now there is no return value. The client can listen to `state_changed` events if it is interested in changed entities as a result of a service call. - -```json -{ - "id": 24, - "type": "call_service", - "domain": "light", - "service": "turn_on", - // Optional - "service_data": { - "entity_id": "light.kitchen" - } -} -``` - -The server will indicate with a message indicating that the service is done executing. - -```json -{ - "id": 24, - "type": "result", - "success": true, - "result": null -} -``` - -### Fetching states - -This will get a dump of all the current states in Home Assistant. - -```json -{ - "id": 19, - "type": "get_states" -} -``` - -The server will respond with a result message containing the states. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -### Fetching config - -This will get a dump of the current config in Home Assistant. - -```json -{ - "id": 19, - "type": "get_config" -} -``` - -The server will respond with a result message containing the config. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -### Fetching services - -This will get a dump of the current services in Home Assistant. - -```json -{ - "id": 19, - "type": "get_services" -} -``` - -The server will respond with a result message containing the services. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -### Fetching panels - -This will get a dump of the current registered panels in Home Assistant. - -```json -{ - "id": 19, - "type": "get_panels" -} -``` - -The server will respond with a result message containing the current registered panels. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -### Fetching camera thumbnails - -_Introduced in Home Assistant 0.69._ - -Return a b64 encoded thumbnail of a camera entity. - -```json -{ - "id": 19, - "type": "camera_thumbnail" -} -``` - -The server will respond with a result message containing the thumbnail. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -### Fetching media player thumbnails - -_Introduced in Home Assistant 0.69._ - -Fetch a base64 encoded thumbnail picture for a media player. - -```json -{ - "id": 19, - "type": "media_player_thumbnail", - "entity_id": "media_player.living_room" -} -``` - -The server will respond with the image encoded via base64. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Pings and Pongs - -The API supports receiving a ping from the client and returning a pong. This serves as a heartbeat to ensure the connection is still alive: - -```json -{ - "id": 19, - "type": "ping" -} -``` - -The server must send a pong back as quickly as possible, if the connection is still active: - -```json -{ - "id": 19, - "type": "pong" -} -``` - -## Error handling - -If an error occurs, the `success` key in the `result` message will be set to `false`. It will contain an `error` key containing an object with two keys: `code` and `message`. - -| Code | Description | -| ----- | ------------ | -| 1 | A non-increasing identifier has been supplied. -| 2 | Received message is not in expected format (voluptuous validation error). -| 3 | Requested item cannot be found - -```json -{ - "id": 12, - "type":"result", - "success": false, - "error": { - "code": 2, - "message": "Message incorrectly formatted: expected str for dictionary value @ data['event_type']. Got 100" - } -} -``` diff --git a/website/versioned_docs/version-0.90.0/hassio_addon_config.md b/website/versioned_docs/version-0.90.0/hassio_addon_config.md deleted file mode 100644 index 10d8a237..00000000 --- a/website/versioned_docs/version-0.90.0/hassio_addon_config.md +++ /dev/null @@ -1,211 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.90.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use `jq` inside your shell script to parse this data. However, you might have to install `jq` as a separate package in your container (see `Dockerfile` below). - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -## Add-on Docker file - -All add-ons are based on Alpine Linux 3.6. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | yes | List of supported arch: `armhf`, `armv7`, `aarch64`, `amd64`, `i386`. -| machine | list | no | Default it support any machine type. You can select that this add-on run only on specific machines. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| kernel_modules | bool | no | Map host kernel modules and config into add-on (readonly). -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| auth_api | bool | no | Allow access to Home Assistent user backend. - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. diff --git a/website/versioned_docs/version-0.90.0/hassio_addon_tutorial.md b/website/versioned_docs/version-0.90.0/hassio_addon_tutorial.md deleted file mode 100644 index 2712cc91..00000000 --- a/website/versioned_docs/version-0.90.0/hassio_addon_tutorial.md +++ /dev/null @@ -1,182 +0,0 @@ ---- -title: Tutorial: Making your first add-on -id: version-0.90.0-hassio_addon_tutorial -original_id: hassio_addon_tutorial ---- - -So you've got Home Assistant going and you've been enjoying the built-in add-ons but you're missing this one application. Time to make your own add-on! In Hass.io 0.24 we introduced the option to have local add-ons be build on your device. This is great for developing new add-ons locally. - -To get started with developing add-ons, we first need access to where Hass.io looks for local add-ons. For this you can use the Samba add-on or the SSH add-on. - -For Samba, once you have enabled and started it, your Hass.io instance will show up in your local network tab and share a folder called "addons". This is the folder to store your custom add-ons. - -If you are on macOS and the folder is not showing up automatically, go to Finder and press CMD+K then enter 'smb://hassio.local' - -![Screenshot of Windows Explorer showing a folder on the Hass.io server](/img/en/hass.io/tutorial/samba.png) - -For SSH, you will have to install it. Before you can start it, you will have to have a private/public key pair and store your public key in the add-on config ([see docs for more info][ssh]). Once started, you can SSH to Hass.io and store your custom add-ons in "/addons". - -![Screenshot of Putty connected to Hass.io](/img/en/hass.io/tutorial/ssh.png) - -Once you have located your add-on directory, it's time to get started! - -[ssh]: https://www.home-assistant.io/addons/ssh/ - -## Step 1: The basics - - - Create a new directory called `hello_world` - - Inside that directory create three files. - -`Dockerfile`: -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -`config.json`: -```json -{ - "name": "Hello world", - "version": "1", - "slug": "hello_world", - "description": "My first real add-on!", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {} -} -``` - -`run.sh`: -```bash -echo Hello world! -``` -Make sure your editor is using UNIX-like line breaks (LF), not Dos/Windows (CRLF). - -## Step 2: Installing and testing your add-on - -Now comes the fun part, time to open the Hass.io UI and install and run your add-on. - - - Open the Home Assistant frontend - - Go to the Hass.io panel - - On the top right click the shopping basket to go to the add-on store. - -![Screenshot of the Hass.io main panel](/img/en/hass.io/screenshots/main_panel_addon_store.png) - - - On the top right click the refresh button - - You should now see a new card called "Local" that lists your add-on! - -![Screenshot of the local repository card](/img/en/hass.io/screenshots/local_repository.png) - - - Click on your add-on to go to the add-on details page. - - Install your add-on - - Start your add-on - - Refresh the logs of your add-on, you should now see "Hello world!" in your logs. - -![Screenshot of the add-on logs](/img/en/hass.io/tutorial/addon_hello_world_logs.png) - -### I don't see my add-on?! - -Oops! You clicked refresh in the store and your add-on didn't show up. Or maybe you just updated an option, clicked refresh and saw your add-on disappear. - -When this happens, it means that your `config.json` is invalid. It's either invalid JSON or one of the specified options is incorrect. To see what went wrong, go to the Hass.io panel and in the supervisor card click on "View logs". This should bring you to a page with the logs of the supervisor. Scroll to the bottom and you should be able to find the validation error. - -Once you fixed the error, go to the add-on store and click refresh again. - -## Step 3: Hosting a server - -Until now we've been able to do some basic stuff, but it's not very useful yet. So let's take it one step further and host a server that we expose on a port. For this we're going to use the built-in HTTP server that comes with Python 3. - -To do this, we will need to update our files as follows: - - - `Dockerfile`: Install Python 3 - - `config.json`: Make the port from the container available on the host - - `run.sh`: Run the Python 3 command to start the HTTP server - -Add to your `Dockerfile` before `RUN`: - -``` -# Install requirements for add-on -RUN apk add --no-cache python3 - -# Python 3 HTTP Server serves the current working dir -# So let's set it to our add-on persistent data directory. -WORKDIR /data -``` - -Add "ports" to `config.json`. This will make TCP on port 8000 inside the container available on the host on port 8000. - -```json -{ - "name": "Hello world", - "version": "0.2", - "slug": "hello_world", - "description": "My first real add-on!", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {}, - "ports": { - "8000/tcp": 8000 - } -} -``` - -Update `run.sh` to start the Python 3 server: - -``` -python3 -m http.server -``` - -## Step 4: Installing the update - -Since we updated the version number in our `config.json`, Home Assistant will show an update button when looking at the add-on details. You might have to refresh your browser or click the refresh button in the add-on store for it to show up. If you did not update the version number, you can also uninstall and install the add-on again. After installing the add-on again, make sure you start it. - -Now navigate to [http://hassio.local:8000](http://hassio.local:8000) to see our server in action! - -![Screenshot of the file index served by the add-on](/img/en/hass.io/tutorial/python3-http-server.png) - -## Bonus: Working with add-on options - -In the screenshot you've probably seen that our server only served up 1 file: `options.json`. This file contains the user configuration for this add-on. Because we specified an empty "config" and "schema" in our `config.json`, the file is currently empty. - -Let's see if we can get some data into that file! - -To do this, we need to specify the default options and a schema for the user to change the options. - -Change the options and schema entries in your `config.json` with the following: - -```json -{ - … - - "options": { - "beer": true, - "wine": true, - "liquor": false, - "name": "world", - "year": 2017 - }, - "schema": { - "beer": "bool", - "wine": "bool", - "liquor": "bool", - "name": "str", - "year": "int" - }, - - … -} -``` - -Refresh the add-on store and re-install your add-on. You will now see the options available in the add-on config screen. When you now go back to our Python 3 server and download `options.json`, you'll see the options you set. [Example of how options.json can be used inside `run.sh`](https://github.com/home-assistant/hassio-addons/blob/master/mosquitto/run.sh#L4-L6) diff --git a/website/versioned_docs/version-0.90.0/maintenance.md b/website/versioned_docs/version-0.90.0/maintenance.md deleted file mode 100644 index c4103c71..00000000 --- a/website/versioned_docs/version-0.90.0/maintenance.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Maintenance -id: version-0.90.0-maintenance -original_id: maintenance ---- - -This page documents a couple of points for maintaining the Home Assistant code. Most of the tasks don't need to be performed on a regular base thus the steps, used tools, or details are preserved here. - -## Source code - -### Line separator - -People are using various operating systems to develop components and platforms for Home Assistant. This could lead to different line endings on file. We prefer `LN`. Especially Microsoft Windows tools tend to use `CRLF`. - -```bash -$ find homeassistant -name "*.py" -exec file {} \; | grep BOM -$ find homeassistant -name "*.py" -exec file {} \; | grep CRLF -``` - -To fix the line separator, use `dos2unix` or `sed`. - -```bash -$ dos2unix homeassistant/components/notify/kodi.py -``` - -### File permissions - -Most files don't need to the be executable. `0644` is fine. - -### Dependencies - -A lot of components and platforms depends on third-party Python modules. The dependencies which are stored in the `requirements_*.txt` files are tracked by [Requires.io](https://requires.io/github/home-assistant/home-assistant/requirements/?branch=dev). - -If you update the requirements of a component/platform through the `REQUIREMENTS = ['modules-xyz==0.3']` entry, run the provided script to update the `requirements_*.txt` file(s). - -```bash -$ script/gen_requirements_all.py -``` - -Start a test run of Home Assistant. If that was successful, include all files in a Pull Request. Add a short summary of the changes, a sample configuration entry, details about the tests you performed to ensure the update works, and other useful information to the description. - - -## Documentation - -- Merge `current` into `next` on a regular base. -- Optimize the images. - diff --git a/website/versioned_docs/version-0.91.0/asyncio_working_with_async.md b/website/versioned_docs/version-0.91.0/asyncio_working_with_async.md deleted file mode 100644 index f72c9773..00000000 --- a/website/versioned_docs/version-0.91.0/asyncio_working_with_async.md +++ /dev/null @@ -1,108 +0,0 @@ ---- -title: Working with Async -id: version-0.91.0-asyncio_working_with_async -original_id: asyncio_working_with_async ---- - -Although we have a backwards compatible API, using the async core directly will be a lot faster. Most core components have already been rewritten to leverage the async core. This includes the EntityComponent helper (foundation of light, switch, etc), scripts, groups and automation. - -## Interacting with the core - -[All methods in the Home Assistant core][dev-docs] are implemented in two flavors: an async version and a version to be called from other threads. The versions for other are merely wrappers that call the async version in a threadsafe manner. - -So if you are making calls to the core (the hass object) from within a callback or coroutine, use the methods that start with async_. If you need to call an async_ function that is a coroutine, your task must also be a coroutine. - -## Implementing an async component - -To make a component async, implement an async_setup. - -```python -def setup(hass, config): - # Setup your component outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup(hass, config): - # Setup your component inside of the event loop. -``` - -## Implementing an async platform - -For platforms we support async setup. Instead of setup_platform you need to have a coroutine async_setup_platform. - -```python -setup_platform(hass, config, add_entities, discovery_info=None): - # Setup your platform outside of the event loop. -``` - -Will turn into: - -```python -async def async_setup_platform(hass, config, async_add_entities, - discovery_info=None): - # Setup your platform inside of the event loop -``` - -The only difference with the original parameters is that the `add_entities` function has been replaced by the async friendly callback `async_add_entities`. - -## Implementing an async entity - -You can make your entity async friendly by converting your update method to be async. This requires the dependency of your entities to also be async friendly! - -```python -class MyEntity(Entity): - def update(self): - """Retrieve latest state.""" - self._state = fetch_state() -``` - -Will turn into: - -```python -class MyEntity(Entity): - async def async_update(self): - """Retrieve latest state.""" - self._state = await async_fetch_state() -``` - -Make sure that all properties defined on your entity do not result in I/O being done. All data has to be fetched inside the update method and cached on the entity. This is because these properties are read from within the event loop and thus doing I/O will result in the core of Home Assistant waiting until your I/O is done. - -## Calling async functions from threads - -Sometimes it will happen that you’re in a thread and you want to call a function that is only available as async. Home Assistant includes a few async helper utilities to help with this. - -In the following example, `say_hello` will schedule `async_say_hello` and block till the function has run and get the result back. - -```python -import asyncio - -def say_hello(hass, target): - return asyncio.run_coroutine_threadsafe( - async_say_hello(hass, target), hass.loop).result() - -async def async_say_hello(hass, target): - return "Hello {}!".format(target) -``` - -## Calling sync functions from async - -If you are running inside an async context, it might sometimes be necessary to call a sync function. Do this like this: - -```python -# hub.update() is a sync function. -result = await hass.async_add_executor_job(hub.update) -``` - -## Starting independent task from async - -If you want to spawn a task that will not block the current async context, you can choose to create it as a task on the event loop. It will then be executed in parallel. - -```python -hass.async_create_task(async_say_hello(hass, target)) -``` - - -[dev-docs]: https://dev-docs.home-assistant.io/en/master/api/core.html -[dev-docs-async]: https://dev-docs.home-assistant.io/en/dev/api/util.html#module-homeassistant.util.async diff --git a/website/versioned_docs/version-0.91.0/creating_component_code_review.md b/website/versioned_docs/version-0.91.0/creating_component_code_review.md deleted file mode 100644 index 8ad17031..00000000 --- a/website/versioned_docs/version-0.91.0/creating_component_code_review.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Checklist for creating a component -id: version-0.91.0-creating_component_code_review -original_id: creating_component_code_review ---- - -A checklist of things to do when you're adding a new component. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on components level - -### 1. Requirements - - 1. Requirement version pinned: `REQUIREMENTS = ['phue==0.8.1']` - 2. We no longer want requirements hosted on GitHub. Please upload to PyPi. - 3. Requirements should [only be imported inside functions](creating_component_deps_and_reqs.md). This is necessary because requirements are installed on the fly. - -### 2. Configuration - - 1. Voluptuous schema present for [configuration validation](development_validation.md) - 2. Default parameters specified in voluptuous schema, not in `setup(…)` - 3. Schema using as many generic config keys as possible from `homeassistant.const` - 4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`. - 5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation` - 6. Never depend on users adding things to `customize` to configure behavior inside your component. - -### 3. Component/platform communication - - 1. If you need to share global data with platforms, use the dictionary `hass.data`. `hass.data[DATA_XY]` while `XY` is the component is preferred over `hass.data[DOMAIN]`. - 2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`. - - -### 4. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - -```python -# bad -status = requests.get(url('/status')) - -# good -from phue import Bridge -bridge = Bridge(...) -status = bridge.status() -``` - -### 5. Make your pull request as small as possible -Keep a new integration to the minimum functionality needed for someone to get value out of the integration. This allows reviewers to sign off on smaller chunks of code one at a time, and lets us get your new integration/features in sooner. **Pull requests containing large code dumps will not be a priority for review and may be closed.** -- Limit to a single platform -- Do not add features not needed to directly support the single platform (such as custom services) -- Do not mix clean-ups and new features in a single pull request. -- Do not solve several issues in a single pull request. -- Do not submit pull requests that depend on other work which is still unmerged. - -### 6. Event names -Prefix component event names with the component name itself. For example, use `netatmo_person` instead of `person` for the `netatmo` component. - -### 7. Tests -Strongly consider adding tests for your component to minimize future regressions. diff --git a/website/versioned_docs/version-0.91.0/creating_platform_example_light.md b/website/versioned_docs/version-0.91.0/creating_platform_example_light.md deleted file mode 100644 index 300d3515..00000000 --- a/website/versioned_docs/version-0.91.0/creating_platform_example_light.md +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: Example light platform -id: version-0.91.0-creating_platform_example_light -original_id: creating_platform_example_light ---- - -This example is for adding support for the imaginary Awesome Lights. It shows the different best practices for developing a platform. - -Similar to Example Sensor Platform, copy the code below, and create it as a file in `/custom_components/awesomelights/light.py`. - -Add the following to your configuration.yaml: - -```yaml -light: - - platform: awesomelights - host: HOST_HERE - username: USERNAME_HERE - password: PASSWORD_HERE_OR_secrets.yaml -``` - -Note the `platform` name matches the directory name that contains the source code. - -```python -import logging - -import voluptuous as vol - -# Import the device class from the component that you want to support -from homeassistant.components.light import ATTR_BRIGHTNESS, Light, PLATFORM_SCHEMA -from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD -import homeassistant.helpers.config_validation as cv - -# Home Assistant depends on 3rd party packages for API specific code. -REQUIREMENTS = ['awesome_lights==1.2.3'] - -_LOGGER = logging.getLogger(__name__) - -# Validation of the user's configuration -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_USERNAME, default='admin'): cv.string, - vol.Optional(CONF_PASSWORD): cv.string, -}) - - -def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the Awesome Light platform.""" - import awesomelights - - # Assign configuration variables. The configuration check takes care they are - # present. - host = config.get(CONF_HOST) - username = config.get(CONF_USERNAME) - password = config.get(CONF_PASSWORD) - - # Setup connection with devices/cloud - hub = awesomelights.Hub(host, username, password) - - # Verify that passed in configuration works - if not hub.is_valid_login(): - _LOGGER.error("Could not connect to AwesomeLight hub") - return - - # Add devices - add_devices(AwesomeLight(light) for light in hub.lights()) - - - -class AwesomeLight(Light): - """Representation of an Awesome Light.""" - - def __init__(self, light): - """Initialize an AwesomeLight.""" - self._light = light - self._name = light.name - self._state = None - self._brightness = None - - @property - def name(self): - """Return the display name of this light.""" - return self._name - - @property - def brightness(self): - """Return the brightness of the light. - - This method is optional. Removing it indicates to Home Assistant - that brightness is not supported for this light. - """ - return self._brightness - - @property - def is_on(self): - """Return true if light is on.""" - return self._state - - def turn_on(self, **kwargs): - """Instruct the light to turn on. - - You can skip the brightness part if your light does not support - brightness control. - """ - self._light.brightness = kwargs.get(ATTR_BRIGHTNESS, 255) - self._light.turn_on() - - def turn_off(self, **kwargs): - """Instruct the light to turn off.""" - self._light.turn_off() - - def update(self): - """Fetch new state data for this light. - - This is the only method that should fetch new data for Home Assistant. - """ - self._light.update() - self._state = self._light.is_on() - self._brightness = self._light.brightness -``` diff --git a/website/versioned_docs/version-0.91.0/creating_platform_example_sensor.md b/website/versioned_docs/version-0.91.0/creating_platform_example_sensor.md deleted file mode 100644 index 419e705f..00000000 --- a/website/versioned_docs/version-0.91.0/creating_platform_example_sensor.md +++ /dev/null @@ -1,61 +0,0 @@ ---- -title: Example sensor platform -id: version-0.91.0-creating_platform_example_sensor -original_id: creating_platform_example_sensor ---- - -This is a minimum implementation of a platform for the sensor component. - -### Installation - -Copy the code below and create it as a file in `/custom_components/example/sensor.py`. - -Add the following to your `configuration.yaml` file: - -```yaml -# Example configuration.yaml entry -sensor: - platform: example -``` - -### Code - -```python -from homeassistant.const import TEMP_CELSIUS -from homeassistant.helpers.entity import Entity - - -def setup_platform(hass, config, add_devices, discovery_info=None): - """Setup the sensor platform.""" - add_devices([ExampleSensor()]) - - -class ExampleSensor(Entity): - """Representation of a Sensor.""" - - def __init__(self): - """Initialize the sensor.""" - self._state = None - - @property - def name(self): - """Return the name of the sensor.""" - return 'Example Temperature' - - @property - def state(self): - """Return the state of the sensor.""" - return self._state - - @property - def unit_of_measurement(self): - """Return the unit of measurement.""" - return TEMP_CELSIUS - - def update(self): - """Fetch new state data for the sensor. - - This is the only method that should fetch new data for Home Assistant. - """ - self._state = 23 -``` diff --git a/website/versioned_docs/version-0.91.0/dev_101_events.md b/website/versioned_docs/version-0.91.0/dev_101_events.md deleted file mode 100644 index a4352ddd..00000000 --- a/website/versioned_docs/version-0.91.0/dev_101_events.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Using Events -id: version-0.91.0-dev_101_events -original_id: dev_101_events ---- - -The core of Home Assistant is driven by events. That means that if you want to respond to something happening, you'll have to respond to events. Most of the times you won't interact directly with the event system but use one of the [event listener helpers][helpers]. - -The event system is very flexible. There are no limitations on the event type, as long as it's a string. Each event can contain data. The data is a dictionary that can contain any data as long as it's JSON serializable. This means that you can use number, string, dictionary and list. - -[List of events that Home Assistant fires.][object] - -## Firing events - -To fire an event, you have to interact with the event bus. The event bus is available on the Home Assistant instance as `hass.bus`. - -Example component that will fire an event when loaded. Note that custom event names are prefixed with the component name. - -```python -DOMAIN = 'example_component' - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - # Fire event example_component_my_cool_event with event data answer=42 - hass.bus.fire('example_component_my_cool_event', { - 'answer': 42 - }) - - # Return successful setup - return True -``` - -## Listening to events - -Most of the times you'll not be firing events but instead listen to events. For example, the state change of an entity is broadcasted as an event. - -```python -DOMAIN = 'example_component' - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - count = 0 - - # Listener to handle fired events - def handle_event(event): - nonlocal count - count += 1 - print('Answer {0} is: {1}'.format(count, event.data.get('answer'))) - - # Listen for when example_component_my_cool_event is fired - hass.bus.listen('example_component_my_cool_event', handle_event) - - # Return successful setup - return True -``` - -### Helpers - -Home Assistant comes with a lot of bundled helpers to listen to specific types of event. There are helpers to track a point in time, to track a time interval, a state change or the sun set. [See available methods.][helpers] - -[helpers]: https://dev-docs.home-assistant.io/en/master/api/helpers.html#module-homeassistant.helpers.event -[object]: https://www.home-assistant.io/docs/configuration/events/ diff --git a/website/versioned_docs/version-0.91.0/entity_media_player.md b/website/versioned_docs/version-0.91.0/entity_media_player.md deleted file mode 100644 index 2d14ab99..00000000 --- a/website/versioned_docs/version-0.91.0/entity_media_player.md +++ /dev/null @@ -1,68 +0,0 @@ ---- -title: Media Player Entity -sidebar_label: Media Player -id: version-0.91.0-entity_media_player -original_id: entity_media_player ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| sound_mode | string | None | The current sound mode of the media player -| sound_mode_list | list | None | Dynamic list of available sound modes (set by platform, empty means sound mode not supported) -| source | string | None | The currently selected input source for the media player. -| source_list | list | None | The list of possible input sources for the media player. (This list should contain human readable names, suitible for frontend display) - - -## Methods -### Select sound mode -Optional. Switch the sound mode of the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - def async_select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - -### Select source -Optional. Switch the selected input source for the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_source(self, source): - """Select input source.""" - - def async_select_source(self, source): - """Select input source.""" - -### Mediatype -Required. Returns one of the defined constants from the below list that matches the mediatype - -| CONST | -|-------| -|MEDIA_TYPE_MUSIC| -|MEDIA_TYPE_TVSHOW| -|MEDIA_TYPE_MOVIE| -|MEDIA_TYPE_VIDEO| -|MEDIA_TYPE_EPISODE| -|MEDIA_TYPE_CHANNEL| -|MEDIA_TYPE_PLAYLIST| -|MEDIA_TYPE_IMAGE| -|MEDIA_TYPE_URL| -|MEDIA_TYPE_GAME| - - class MyMediaPlayer(MediaPlayerDevice): - # Implement the following method. - - def media_content_type(self): - """Content type of current playing media.""" - diff --git a/website/versioned_docs/version-0.91.0/entity_sensor.md b/website/versioned_docs/version-0.91.0/entity_sensor.md deleted file mode 100644 index 7ddced03..00000000 --- a/website/versioned_docs/version-0.91.0/entity_sensor.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -title: Sensor Entity -sidebar_label: Sensor -id: version-0.91.0-entity_sensor -original_id: entity_sensor ---- - -A sensor is a read-only entity that provides some information. Information has a value and optionally, a unit of measurement. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| state | string | **Required** | The value of the sensor. -| unit_of_measurement | string | `None` | The unit of measurement that the sensor is expressed in. -| device_class | string | `None` | Type of sensor. - -### Available device classes - -If specifying a device class, your sensor entity will need to also return the correct unit of measurement. - -| Type | Unit | Description -| ---- | ---- | ----------- -| battery | % | % of battery that is left. -| humidity | % | % of humidity in the air. -| illuminance | lx/lm | Light level. -| temperature | °C/°F | Temperature. -| timestamp | ISO8601 | Timestamp. -| power | W,kW | Power. -| pressure | hPa,mbar | Pressure. diff --git a/website/versioned_docs/version-0.91.0/integration_quality_scale_index.md b/website/versioned_docs/version-0.91.0/integration_quality_scale_index.md deleted file mode 100644 index 4dcce62d..00000000 --- a/website/versioned_docs/version-0.91.0/integration_quality_scale_index.md +++ /dev/null @@ -1,57 +0,0 @@ ---- -title: Integration Quality Scale -sidebar_label: Introduction -id: version-0.91.0-integration_quality_scale_index -original_id: integration_quality_scale_index ---- - -The Integration Quality Scale scores each integration based on the code quality and user experience. Each level of the quality scale consists of a list of requirements. If an integration matches all requirements, it's considered to have reached that level. - -> Suggestions for changes can be done by creating an issue in the [architecture repo](https://github.com/home-assistant/architecture/issues/). - -# No score - -This integration passes the bare minimum requirements to become part of the index. - - - Satisfy all requirements for [creating components](creating_component_code_review.md) and [creating platforms](creating_platform_code_review.md). - - Configurable via `configuration.yaml` - -# Silver 🥈 - -This integration is able to cope when things go wrong. It will not print any exceptions nor will it fill the log with retry attempts. - -- Connection/configuration is handled via a component. -- Set an appropriate `SCAN_INTERVAL` (if a polling integration) -- Raise `PlatformNotReady` if unable to connect during platform setup (if appropriate) -- Handles expiration of auth credentials. Refresh if possible or print correct error and fail setup. If based on a config entry, should trigger a new config entry flow to re-authorize. -- Handles internet unavailable. Log a warning once when unavailable, log once when reconnected. -- Handles device/service unavailable. Log a warning once when unavailable, log once when reconnected. -- Set `available` property to `False` if appropriate ([docs](entity_index.md#generic-properties)) -- Entities have unique ID (if available) ([docs](entity_registry_index.md#unique-id-requirements)) - -# Gold 🥇 - -This is a solid integration that is able to survive poor conditions and can be configured via the user interface. - -- Configurable via config entries. - - Don't allow configuring already configured device/service (example: no 2 entries for same hub) - - Tests for the config flow - - Discoverable (if available) -- Entities have device info (if available) ([docs](device_registry_index.md#defining-devices)) -- States are translated in the frontend (text-based sensors only, [docs](internationalization_index.md)) -- Tests for reading data from/controlling the integration ([docs](development_testing.md)) -- Has a code owner - -# Platinum 🏆 - -Best of the best. The integration is completely async, meaning it's super fast. Integrations that reach platinum level will require approval by the code owner for each PR. - -- Set appropriate `PARALLEL_UPDATES` constant -- Support config entry unloading (called when config entry is removed) -- Integration + dependency are async -- Uses aiohttp and allows passing in websession (if making HTTP requests) - -# Internal 🏠 - -Integrations which are part of Home Assistant are not rated but marked as **internal**. - diff --git a/website/versioned_docs/version-0.91.2/app_integration_notifications.md b/website/versioned_docs/version-0.91.2/app_integration_notifications.md deleted file mode 100644 index 1e441194..00000000 --- a/website/versioned_docs/version-0.91.2/app_integration_notifications.md +++ /dev/null @@ -1,239 +0,0 @@ ---- -title: Push Notifications -id: version-0.91.2-app_integration_notifications -original_id: app_integration_notifications ---- - -The `mobile_app` component has a notify platform built in that allows for a generic way to send push notifications to your users without requiring installation of a external custom component. - -## Enabling push notifications - -To enable the notify platform for your application, you must set two keys in the `app_data` object during the initial registration or later update of an existing registration. - -| Key | Type | Description -| --- | ---- | ----------- -| `push_token` | string | A push notification token unique to your users device. For example, this could be a APNS token or a FCM Instance ID/token. -| `push_url` | string | The URL on your server that push notifications will be HTTP POSTed to. - -You should advise the user to restart Home Assistant after you set these keys in order for them to see the notify target. It will have the format `notify.mobile_app_`. - -## Deploying a server component - -The notify platform doesn't concern itself with how to notify your users. It simply forwards a notification to your external server where you should actually handle the request. -This approach allows you to maintain full control over your push notification infrastructure. - -See the next section of this document for an example server implementation of a push notification forwarder that uses Firebase Cloud Functions and Firebase Cloud Messaging. - -Your server should accept a HTTP POST payload like this: - -```json -{ - "message": "Hello World", - "title": "Test message sent via mobile_app.notify", - "push_token": "my-secure-token", - "registration_info": { - "app_id": "io.home-assistant.iOS", - "app_version": "1.0.0", - "os_version": "12.2" - }, - "data": { - "key": "value" - } -} -``` - -It should respond with a 201 status code assuming the notification was queued for delivery successfully. - -### Errors - -If an error occurs you should return a description of what went wrong with a status code _other than_ 201 or 429. An error response must be a JSON object and can contain one of the following keys: - -| Key | Type | Description -| --- | ---- | ----------- -| `errorMessage` | string | If provided, it will be appended to a preset error message. For example, if `errorMessage` is "Could not communicate with Apple" it will be output in the log like "Internal server error, please try again later: Could not communicate with Apple" -| `message` | string | If provided, it will be output directly to the logs at the warning log level. - -No matter what key you use, you should try to be as descriptive as possible about what went wrong and, if possible, how the user can fix it. - -### Rate limits - -The notify platform also supports exposing rate limits to users. Home Assistant suggests you implement a conservative rate limit to keep your costs low and also so that users don't overload themselves with too many notifications. -For reference, Home Assistant Companion has a maximum sendable notifications per 24 hours of 150 notifications. The rate limit resets for all users at midnight, UTC. You of course are free to use whatever configuration for your own rate limiting. - -If you choose to implement rate limiting, your successful server response should look like the following: - -```json -{ - "rateLimits": { - "successful": 1, - "errors": 5, - "maximum": 150, - "resetsAt": "2019-04-08T00:00:00.000Z" - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `successful` | integer | The number of successful push notifications the user has sent during the rate limit period. -| `errors` | integer | The number of failed push notifications the user has sent during the rate limit period. -| `maximum` | integer | The maximum number of push notifications the user can send during the users rate limit period. -| `resetsAt` | ISO8601 timestamp | The timestamp that the users rate limit period expires at. Must be provided in the UTC timezone. - -The rate limits will be output to the log at the warning log level after every notification is successfully sent. Home Assistant will also output the exact time remaining until the rate limit period resets. - -Once the user hits their maximum amount of notifications sent in the rate limit period, you should start responding with a 429 status code until the rate limit period expires. The response object can optionally contain a key, `message` which will be output to the Home Assistant log instead of the standard error message. - -The notify platform does not itself implement any kind of rate limit protections. Users will be able to keep sending you notifications, so you should reject them with a 429 status code as early in your logic as possible. - -## Example server implementation -The below code is a Firebase Cloud Function that forwards notifications to Firebase Cloud Messaging. To deploy this, you should create a new Firestore database named `rateLimits`. Then, you can deploy the following code. -Also, ensure that you have properly configured your project with the correct authentication keys for APNS and FCM. - -```javascript -'use strict'; - -const functions = require('firebase-functions'); -const admin = require('firebase-admin'); -admin.initializeApp(); - -var db = admin.firestore(); - -const MAX_NOTIFICATIONS_PER_DAY = 150; - -exports.sendPushNotification = functions.https.onRequest(async (req, res) => { - console.log('Received payload', req.body); - var today = getToday(); - var token = req.body.push_token; - var ref = db.collection('rateLimits').doc(today).collection('tokens').doc(token); - - var payload = { - notification: { - body: req.body.message, - }, - token: token, - }; - - if(req.body.title) { - payload.notification.title = req.body.title; - } - - if(req.body.data) { - if(req.body.data.android) { - payload.android = req.body.data.android; - } - if(req.body.data.apns) { - payload.apns = req.body.data.apns; - } - if(req.body.data.data) { - payload.data = req.body.data.data; - } - if(req.body.data.webpush) { - payload.webpush = req.body.data.webpush; - } - } - - console.log('Notification payload', JSON.stringify(payload)); - - var docExists = false; - var docData = { - deliveredCount: 0, - errorCount: 0, - totalCount: 0, - }; - - try { - let currentDoc = await ref.get(); - docExists = currentDoc.exists; - if(currentDoc.exists) { - docData = currentDoc.data(); - } - } catch(err) { - console.error('Error getting document!', err); - return handleError(res, 'getDoc', err); - } - - if(docData.deliveredCount > MAX_NOTIFICATIONS_PER_DAY) { - return res.status(429).send({ - errorType: 'RateLimited', - message: 'The given target has reached the maximum number of notifications allowed per day. Please try again later.', - target: token, - rateLimits: getRateLimitsObject(docData), - }); - } - - docData.totalCount = docData.totalCount + 1; - - var messageId; - try { - messageId = await admin.messaging().send(payload); - docData.deliveredCount = docData.deliveredCount + 1; - } catch(err) { - docData.errorCount = docData.errorCount + 1; - await setRateLimitDoc(ref, docExists, docData, res); - return handleError(res, 'sendNotification', err); - } - - console.log('Successfully sent message:', messageId); - - await setRateLimitDoc(ref, docExists, docData, res); - - return res.status(201).send({ - messageId: messageId, - sentPayload: payload, - target: token, - rateLimits: getRateLimitsObject(docData), - }); - -}); - -async function setRateLimitDoc(ref, docExists, docData, res) { - try { - if(docExists) { - console.log('Updating existing doc!'); - await ref.update(docData); - } else { - console.log('Creating new doc!'); - await ref.set(docData); - } - } catch(err) { - if(docExists) { - console.error('Error updating document!', err); - } else { - console.error('Error creating document!', err); - } - return handleError(res, 'setDocument', err); - } - return true; -} - -function handleError(res, step, incomingError) { - if (!incomingError) return null; - console.error('InternalError during', step, incomingError); - return res.status(500).send({ - errorType: 'InternalError', - errorStep: step, - message: incomingError.message, - }); -} - -function getToday() { - var today = new Date(); - var dd = String(today.getDate()).padStart(2, '0'); - var mm = String(today.getMonth() + 1).padStart(2, '0'); - var yyyy = today.getFullYear(); - return yyyy + mm + dd; -} - -function getRateLimitsObject(doc) { - var d = new Date(); - return { - successful: (doc.deliveredCount || 0), - errors: (doc.errorCount || 0), - total: (doc.totalCount || 0), - maximum: MAX_NOTIFICATIONS_PER_DAY, - remaining: (MAX_NOTIFICATIONS_PER_DAY - doc.deliveredCount), - resetsAt: new Date(d.getFullYear(), d.getMonth(), d.getDate()+1) - }; -} -``` diff --git a/website/versioned_docs/version-0.91.2/app_integration_sending_data.md b/website/versioned_docs/version-0.91.2/app_integration_sending_data.md deleted file mode 100644 index 0e005921..00000000 --- a/website/versioned_docs/version-0.91.2/app_integration_sending_data.md +++ /dev/null @@ -1,230 +0,0 @@ ---- -title: Sending data home -id: version-0.91.2-app_integration_sending_data -original_id: app_integration_sending_data ---- - -Once you have registered your app with the mobile app component, you can start interacting with Home Assistant via the provided webhook information. - -The first step is to turn the returned webhook ID into a full URL: `/api/webhook/`. This will be the only url that we will need for all our interactions. The webhook endpoint will not require authenticated requests. - -If you were provided a Cloudhook URL during registration, you should use that by default and only fall back to a constructed URL as described above if that request fails. - -If you were provided a remote UI URL during registration, you should use that as the `instance_url` when constructing a URL and only fallback to the user provided URL if the remote UI URL fails. - -To summarize, here's how requests should be made: - -1. If you have a Cloudhook URL, use that until a request fails. When a request fails, go to step 2. -2. If you have a remote UI URL, use that to construct a webhook URL: `/api/webhook/`. When a request fails, go to step 3. -3. Construct a webhook URL using the instance URL provided during setup: `/api/webhook/`. - -## Short note on instance URLs - -Some users have configured Home Assistant to be available outside of their home network using a dynamic DNS service. There are some routers that don't support hairpinning / NAT loopback: a device sending data from inside the routers network, via the externally configured DNS service, to Home Asisstant, which also resides inside the local network. - -To work around this, the app should record which WiFi SSID is the users home network, and use a direct connection when connected to the home WiFi network. - -## Interaction basics - -### Request - -All interaction will be done by making HTTP POST requests to the webhook url. These requests do not need to contain authentication. - -The payload format depends on the type of interaction, but it all shares a common base: - -```json5 -{ - "type": "", - "data": {} -} -``` - -If you received a `secret` during registration, you **MUST** encrypt your message and put it in the payload like this: - -```json5 -{ - "type": "encrypted", - "encrypted": true, - "encrypted_data": "" -} -``` - -### Response - -As a general rule, expect to receive a 200 response for all your requests. There are a few cases in which you will receive another code: - -- You will receive a 400 status code if your JSON is invalid. However, you will not receive this error if the encrypted JSON is invalid. -- You will receive a 201 when creating a sensor -- If you receive a 404, the `mobile_app` component most likely isn't loaded. -- Receiving a 410 means the integration has been deleted. You should notify the user and most likely register again. - -## Implementing encryption - -`mobile_app` supports two way encrypted communication via [Sodium](https://libsodium.gitbook.io/doc/). - -> Sodium is a modern, easy-to-use software library for encryption, decryption, signatures, password hashing and more. - -### Choosing a library -Libraries that wrap Sodium exist for most modern programming languages and platforms. Sodium itself is written in C. - -Here are the libraries we suggest using, although you should feel free to use whatever works well for you. - -- Swift/Objective-C: [swift-sodium](https://github.com/jedisct1/swift-sodium) (official library maintained by Sodium developers. - -For other languages, please see the list of [Bindings for other languages](https://download.libsodium.org/doc/bindings_for_other_languages). If more than one choice is available, we recommend using the choice most recently updated. - -### Configuration - -We use the [secret-key cryptography](https://download.libsodium.org/doc/secret-key_cryptography) features of Sodium to encrypt and decrypt payloads. All payloads are JSON encoded in Base64. For Base64 type, use `sodium_base64_VARIANT_ORIGINAL` (that is, "original", no padding, not URL safe). - -### Signaling encryption support - -During registration, you must set `supports_encryption` to `true` to enable encryption. The Home Assistant instance must be able to install `libsodium` to enable encryption. Confirm that you should make all future webhook requests encrypted by the presence of the key `secret` in the initial registration response. -You must store this secret forever. There is no way to recover it via the Home Assistant UI and you should **not** ask users to investigate hidden storage files to re-enter the encryption key. You should create a new registration if encryption ever fails and alert the user. - -## Update device location - -This message will inform Home Assistant of new location information. - -```json -{ - "type": "update_location", - "data": { - "gps": [12.34, 56.78], - "gps_accuracy": 120, - "battery": 45 - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `location_name` | string | Name of the zone the device is in. -| `gps` | latlong | Current location as latitude and longitude. -| `gps_accuracy` | int | GPS accurracy in meters. Must be greater than 0. -| `battery` | int | Percentage of battery the device has left. Must be greater than 0. -| `speed` | int | Speed of the device in meters per second. Must be greater than 0. -| `altitude` | int | Altitude of the device in meters. Must be greater than 0. -| `course` | int | The direction in which the device is traveling, measured in degrees and relative to due north. Must be greater than 0. -| `vertical_accuracy` | int | The accuracy of the altitude value, measured in meters. Must be greater than 0. - -## Call a service - -Call a service in Home Assistant. - -```json -{ - "type": "call_service", - "data": { - "domain": "light", - "service": "turn_on", - "service_data": { - "entity_id": "light.kitchen" - } - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `domain` | string | The domain of the service -| `service` | string | The service name -| `service_data` | dict | The data to send to the service - -## Fire an event - -Fire an event in Home Assistant. - -```json -{ - "type": "fire_event", - "data": { - "event_type": "my_custom_event", - "event_data": { - "something": 50 - } - } -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `event_type` | string | Type of the event to fire -| `event_data` | string | Date of the event to fire - -## Render templates - -Renders one or more templates and returns the result(s). - -```json -{ - "type": "render_template", - "data": { - "my_tpl": { - "template": "Hello {{ name }}, you are {{ states('person.paulus') }}.", - "variables": { - "name": "Paulus" - } - } - } -} -``` - -`data` must contain a map of `key`: `dictionary`. Results will be returned like `{"my_tpl": "Hello Paulus, you are home"}`. This allows for rendering multiple templates in a single call. - -| Key | Type | Description -| --- | ---- | ----------- -| `template` | string | The template to render -| `variables` | Dict | The extra template variables to include. - -## Update registration - -Update your app registration. Use this if the app version changed or any of the other values. - -```json -{ - "type": "update_registration", - "data": { - "app_data": { - "push_token": "abcd", - "push_url": "https://push.mycool.app/push" - }, - "app_version": "2.0.0", - "device_name": "Robbies iPhone", - "manufacturer": "Apple, Inc.", - "model": "iPhone XR", - "os_version": "23.02" - } -} -``` - -All keys are optional. - -| Key | Type | Description -| --- | --- | -- -| `app_data` | Dict | App data can be used if the app has a supporting component that extends mobile_app functionality or wishes to enable the notification platform. -| `app_version` | string | Version of the mobile app. -| `device_name` | string | Name of the device running the app. -| `manufacturer` | string | The manufacturer of the device running the app. -| `model` | string | The model of the device running the app. -| `os_version` | string | The OS version of the device running the app. - -## Get zones - -Get all enabled zones. - -```json -{ - "type": "get_zones" -} -``` - -## Get config - -Returns a version of `/api/config` with values useful for configuring your app. - -```json -{ - "type": "get_config" -} -``` diff --git a/website/versioned_docs/version-0.91.2/app_integration_sensors.md b/website/versioned_docs/version-0.91.2/app_integration_sensors.md deleted file mode 100644 index 7722c3ee..00000000 --- a/website/versioned_docs/version-0.91.2/app_integration_sensors.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Sensors -id: version-0.91.2-app_integration_sensors -original_id: app_integration_sensors ---- - -The `mobile_app` component supports exposing custom sensors that can be managed entirely via your app. - -## Registering a sensor - -All sensors must be registered before they can get updated. You can only register one sensor at a time, unlike updating sensors. - -To register a sensor, make a request to the webhook like this: - -```json -{ - "data": { - "attributes": { - "foo": "bar" - }, - "device_class": "battery", - "icon": "mdi:battery", - "name": "Battery State", - "state": "12345", - "type": "sensor", - "unique_id": "battery_state", - "unit_of_measurement": "%" - }, - "type": "register_sensor" -} -``` - -The valid keys are: - -| Key | Type | Required | Description | -|---------------------|-------------------------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| attributes | object | No | Attributes to attach to the sensor | -| device_class | string | No | One of the valid device classes. [Binary Sensor Classes](https://www.home-assistant.io/components/binary_sensor/#device-class), [Sensor Classes](https://www.home-assistant.io/components/sensor/#device-class) | -| icon | Material Design Icon (string) | No | Must be prefixed `mdi:`. If not provided, default value is `mdi:cellphone` | -| name | string | Yes | The name of the sensor | -| state | bool, float, int, string | Yes | The state of the sensor | -| type | string | Yes | The type of the sensor. Must be one of `binary_sensor` or `sensor` | -| unique_id | string | Yes | A identifier unique to this installation of your app. You'll need this later. Usually best when its a safe version of the sensor name | -| unit_of_measurement | string | No | The unit of measurement for the sensor | - -Sensors will appear as soon as they are registered. - -## Updating a sensor - -Once a sensor has been registered, you need to update it. This is very similar to registering it, but you can update all your sensors at the same time. - -For example, to update the sensor we registered above, you would send this: - -```json -{ - "data": [ - { - "attributes": { - "hello": "world" - }, - "icon": "mdi:battery", - "state": 123, - "type": "sensor", - "unique_id": "battery_state" - } - ], - "type": "update_sensor_states" -} -``` - -Only some of the keys are allowed during updates: - -| Key | Type | Required | Description | -|---------------------|-------------------------------|----------|---------------------------------------------------------------------------------------------------------------------------------------| -| attributes | object | No | Attributes to attach to the sensor | -| icon | Material Design Icon (string) | No | Must be prefixed `mdi:` | -| state | bool, float, int, string | Yes | The state of the sensor | -| type | string | Yes | The type of the sensor. Must be one of `binary_sensor` or `sensor` | -| unique_id | string | Yes | A identifier unique to this installation of your app. You'll need this later. Usually best when its a safe version of the sensor name | - diff --git a/website/versioned_docs/version-0.91.2/app_integration_setup.md b/website/versioned_docs/version-0.91.2/app_integration_setup.md deleted file mode 100644 index de26a092..00000000 --- a/website/versioned_docs/version-0.91.2/app_integration_setup.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Connecting to an instance -id: version-0.91.2-app_integration_setup -original_id: app_integration_setup ---- - -When a user first opens the app, they will need to connect to their local instance to authenticate and register the device. - -## Authenticating the user - -The local instance can be discovered if Home Assistant has the [zeroconf component] configured by searching for `_home-assistant._tcp.local.`. If not configured, the user will need to be asked for the local address of their instance. - -When the address of the instance is known, the app will ask the user to authenticate via [OAuth2 with Home Assistant]. Home Assistant uses IndieAuth, which means that to be able to redirect to a url that triggers your app, you need to take some extra steps. Make sure to read the last paragraph of the "Clients" section thoroughly. - -[zeroconf component]: https://www.home-assistant.io/components/zeroconf -[OAuth2 with Home Assistant]: auth_api.md - -## Registering the device - -_This requires Home Assistant 0.90 or later._ - -Home Assistant has a `mobile_app` component that allows applications to register themselves and interact with the instance. This is a generic component to handle most common mobile application tasks. This component is extendable with custom interactions if your app needs more types of interactions than are offered by this component. - -Once you have tokens to authenticate as a user, it's time to register the app with the mobile app component in Home Assistant. - -### Getting Ready - -First, you must ensure that the `mobile_app` component is loaded. There are two ways to do this: - -- You can publish a Zeroconf/Bonjour record `_hass-mobile-app._tcp.local.` to trigger the automatic load of the `mobile_app` component. You should wait at least 60 seconds after publishing the record before continuing. -- You can ask the user to add `mobile_app` to their configuration.yaml and restart Home Assistant. If the user already has `default_config` in their configuration, then `mobile_app` will have been already loaded. - -You can confirm the `mobile_app` component has been loaded by checking the `components` array of the [`/api/config` REST API call](external_api_rest.md#get-api-config). If you continue to device registration and receive a 404 status code, then it most likely hasn't been loaded yet. - -### Registering the device - -To register the device, make an authenticated POST request to `/api/mobile_app/devices`. [More info on making authenticated requests.](auth_api.md#making-authenticated-requests) - -Example payload to send to the registration endpoint: - -```json -{ - "app_id": "awesome_home", - "app_name": "Awesome Home", - "app_version": "1.2.0", - "device_name": "Robbies iPhone", - "manufacturer": "Apple, Inc.", - "model": "iPhone X", - "os_version": "iOS 10.12", - "supports_encryption": true, - "app_data": { - "push_notification_key": "abcdef", - } -} -``` - -| Key | Required | Type | Description | -| --- | -------- | ---- | ----------- | -| `app_id` | V | string | A unique identifier for this app. -| `app_name` | V | string | Name of the mobile app. -| `app_version` | V | string | Version of the mobile app. -| `device_name` | V | string | Name of the device running the app. -| `manufacturer` | V | string | The manufacturer of the device running the app. -| `model` | V | string | The model of the device running the app. -| `os_version` | V | string | The OS version of the device running the app. -| `supports_encryption` | V | bool | If the app supports encryption. See also the [encryption section](#encryption). -| `app_data` | | Dict | App data can be used if the app has a supporting component that extends `mobile_app` functionality. - -When you get a 200 response, the mobile app is registered with Home Assistant. The response is a JSON document and will contain the URLs on how to interact with the Home Assistant instance. You should permanently store this information. - -```json -{ - "cloudhook_url": "https://hooks.nabu.casa/randomlongstring123", - "remote_ui_url": "https://randomlongstring123.ui.nabu.casa", - "secret": "qwerty", - "webhook_id": "abcdefgh" -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `cloudhook_url` | string | The cloudhook URL provided by Home Assistant Cloud. Only will be provided if user is actively subscribed to Nabu Casa. -| `remote_ui_url` | string | The remote UI URL provided by Home Assistant Cloud. Only will be provided if user is actively subscribed to Nabu Casa. -| `secret` | string | The secret to use for encrypted communication. Will only be included if encryption is supported by both the app and the Home Assistant instance. [More info](app_integration_sending_data.md#implementing-encryption). -| `webhook_id` | string | The webhook ID that can be used to send data back. diff --git a/website/versioned_docs/version-0.91.2/auth_auth_module.md b/website/versioned_docs/version-0.91.2/auth_auth_module.md deleted file mode 100644 index e97a99b4..00000000 --- a/website/versioned_docs/version-0.91.2/auth_auth_module.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Multi-factor Authentication Modules -id: version-0.91.2-auth_auth_module -original_id: auth_auth_module ---- - -Multi-factor Authentication Modules are used in conjunction with [Authentication Provider](auth_auth_provider.html) to provide a fully configurable authentication framework. Each MFA module may provide one multi-factor authentication function. User can enable multiple mfa modules, but can only select one module in login process. - -## Defining an mfa auth module - -> We currently only support built-in mfa auth modules. Support for custom auth modules might arrive in the future. - -Multi-factor Auth modules are defined in `homeassistant/auth/mfa_modules/.py`. The auth module will need to provide an implementation of the `MultiFactorAuthModule` class. - -For an example of a fully implemented auth module, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/mfa_modules/insecure_example.py). - -Multi-factor Auth modules shall extend the following methods of `MultiFactorAuthModule` class. - -| method | Required | Description -| ------ | -------- | ----------- -| `@property def input_schema(self)` | Yes | Return a schema defined the user input form. -| `async def async_setup_flow(self, user_id)` | Yes | Return a SetupFlow to handle the setup workflow. -| `async def async_setup_user(self, user_id, setup_data)` | Yes | Set up user for use this auth module. -| `async def async_depose_user(self, user_id)` | Yes | Remove user information from this auth module. -| `async def async_is_user_setup(self, user_id)` | Yes | Return whether user is set up. -| `async def async_validate(self, user_id, user_input)` | Yes | Given a user_id and user input, return validation result. -| `async def async_initialize_login_mfa_step(self, user_id)` | No | Will be called once before display the mfa step of login flow. This is not initialization for the MFA module but the mfa step in login flow. - -## Setup Flow - -Before user can use a multi-factor auth module, it has to be enabled or set up. All available modules will be listed in user profile page, user can enable the module he/she wants to use. A setup data entry flow will guide user finish the necessary steps. - -Each MFA module need to implement a setup flow handler extends from `mfa_modules.SetupFlow` (if only one simple setup step need, `SetupFlow` can be used as well). For example for Google Authenticator (TOTP, Time-based One Time Password) module, the flow will need to be: -- Generate a secret and store it on instance of setup flow -- Return `async_show_form` with a QR code in the description (injected as base64 via `description_placeholders`) -- User scans code and enters a code to verify it scanned correctly and clock in synced -- TOTP module saved the secret along with user_id, module is enabled for user - -## Workflow - -![Multi Factor Authentication Workflow](/img/en/auth/mfa_workflow.png) - -## Configuration example - -```yaml -# configuration.xml -homeassistant: - auth_providers: - - type: homeassistant - - type: legacy_api_password - auth_mfa_modules: - - type: totp - - type: insecure_example - users: [{'user_id': 'a_32_bytes_length_user_id', 'pin': '123456'}] -``` - -In this example, user will first select from `homeassistant` or `legacy_api_password` auth provider. For `homeassistant` auth provider, user will first input username/password, if that user enabled both `totp` and `insecure_example`, then user need select one auth module, then input Google Authenticator code or input pin code base on the selection. - -> insecure_example is only for demo purpose, please do not use it in production. - -## Validation session - -Not like auth provider, auth module use session to manage the validation. After auth provider validated, mfa module will create a validation session, include an experiation time and user_id from auth provider validate result. Mutli-factor auth module will not only verify the user input, but also verify the session is not expired. The validation session data is stored in your configuration directory. diff --git a/website/versioned_docs/version-0.91.2/config_entries_config_flow_handler.md b/website/versioned_docs/version-0.91.2/config_entries_config_flow_handler.md deleted file mode 100644 index 531be4f4..00000000 --- a/website/versioned_docs/version-0.91.2/config_entries_config_flow_handler.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: Integration Configuration -sidebar_label: Configuration -id: version-0.91.2-config_entries_config_flow_handler -original_id: config_entries_config_flow_handler ---- - -> This option is currently only available for built-in components. - -Integrations can be set up via the user interface by adding support for config entries. Config entries uses the [data flow entry framework](data_entry_flow_index.md) to allow users to create entries. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like Hass.io). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -To register your config flow handler with Home Assistant, register it with the config entries `HANDLERS` registry: - -```python -from homeassistant import config_entries - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(config_entries.ConfigFlow): -``` - -All config flow handlers will also need to add their domain name to the `FLOWS` constant in `homeassistant/config_entries.py`. - -## Discovering your config flow - -Home Assistant has a discovery integration that scans the network for available devices and services and will trigger the config flow of the appropriate integration. Discovery is limited to UPnP and zeroconf/mDNS. - -To have your integration be discovered, you will have to extend the [NetDisco library](https://github.com/home-assistant/netdisco) to be able to find your device. This is done by adding a new discoverable. [See the repository for examples of existing discoverable.](https://github.com/home-assistant/netdisco/tree/master/netdisco/discoverables) - -Once done, you will have to update the discovery integration to make it aware which discovery maps to which integration, by updating [this list](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery/__init__.py#L55). - -Finally, you will have to add support to your config flow to be triggered from discovery. This is done by adding a new discovery step. Make sure that your discovery step does not automatically create an entry. All discovered config flows are required to have a confirmation from the user. - -Once discovered, the user will be notified that they can continue the flow from the config panel. - -```python -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` - -When the translations are merged into Home Assistant, they will be automatically uploaded to [Lokalise](https://lokalise.co/) where the translation team will help to translate them in other languages. [More info on translating Home Assistant.](internationalization_translation.md) - -## Triggering other config flows - -If you are writing an integration that discovers other integrations, you will want to trigger their config flows so the user can set them up. Do this by passing a source parameter and optional user input when initializing the config entry: - -```python -await hass.config_entries.flow.async_init( - 'hue', data=discovery_info, - context={'source': config_entries.SOURCE_DISCOVERY}) -``` diff --git a/website/versioned_docs/version-0.91.2/config_entries_index.md b/website/versioned_docs/version-0.91.2/config_entries_index.md deleted file mode 100644 index cdadaa2b..00000000 --- a/website/versioned_docs/version-0.91.2/config_entries_index.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: Config Entries -sidebar_label: Introduction -id: version-0.91.2-config_entries_index -original_id: config_entries_index ---- - -Config Entries are configuration data that are persistently stored by Home Assistant. A config entry is created by a user via the UI. The UI flow is powered by a [config flow handler](config_entries_config_flow_handler.md) as defined by the component. Config entries can also have an extra [options flow handler](config_entries_options_flow_handler.md), also defined by the component. - -## Lifecycle - -| State | Description | -| ----- | ----------- | -| not loaded | The config entry has not been loaded. This is the initial state when a config entry is created or when Home Assistant is restarted. | -| loaded | The config entry has been loaded. | -| setup error | An error occurred when trying to set up the config entry. | -| setup retry | A dependency of the config entry was not ready yet. Home Assistant will automatically retry loading this config entry in the future. Time between attempts will automatically increase. -| migration error | The config entry had to be migrated to a newer version, but the migration failed. -| failed unload | The config entry was attempted to be unloaded, but this was either not supported or it raised an exception. - - - -G - -not loaded - -not loaded - -loaded - -loaded - -not loaded->loaded - - - -setup error - -setup error - -not loaded->setup error - - - -setup retry - -setup retry - -not loaded->setup retry - - - -migration error - -migration error - -not loaded->migration error - - - -loaded->not loaded - - - -failed unload - -failed unload - -loaded->failed unload - - - -setup error->not loaded - - - -setup retry->not loaded - - - - - - - - -## Setting up an entry - -During startup, Home Assistant first calls the [normal component setup](https://developers.home-assistant.io/docs/en/creating_component_index.html), -and then call the method `async_setup_entry(hass, entry)` for each entry. If a new Config Entry is -created at runtime, Home Assistant will also call `async_setup_entry(hass, entry)` ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L119)). - -#### For platforms - -If a component includes platforms, it will need to forward the Config Entry to the platform. This can -be done by calling the forward function on the config entry manager ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/bridge.py#L81)): - -```python -# Use `hass.async_add_job` to avoid a circular dependency between the platform and the component -hass.async_add_job(hass.config_entries.async_forward_entry_setup(config_entry, 'light')) -``` - -For a platform to support config entries, it will need to add a setup entry method ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/light/hue.py#L60)): - -```python -async def async_setup_entry(hass, config_entry, async_add_devices): -``` - -## Unloading entries - -Components can optionally support unloading a config entry. When unloading an entry, the component needs to clean up all entities, unsubscribe any event listener and close all connections. To implement this, add `async_unload_entry(hass, entry)` to your component ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L136)). - -For each platform that you forwarded the config entry to, you will need to forward the unloading too. - -```python -await self.hass.config_entries.async_forward_entry_unload(self.config_entry, 'light') -``` - -If you need to clean up resources used by an entity in a platform, have the entity implement the [`async_will_remove_from_hass`](entity_index.md#async_will_remove_from_hass) method. - -## Removal of entries - -If a component needs to clean up code when an entry is removed, it can define a removal method: - -```python -async def async_remove_entry(hass, entry) -> None: - """Handle removal of an entry.""" -``` diff --git a/website/versioned_docs/version-0.91.2/config_entries_options_flow_handler.md b/website/versioned_docs/version-0.91.2/config_entries_options_flow_handler.md deleted file mode 100644 index e6eaa2ba..00000000 --- a/website/versioned_docs/version-0.91.2/config_entries_options_flow_handler.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Integration Configuration Options -sidebar_label: Configuration Options -id: version-0.91.2-config_entries_options_flow_handler -original_id: config_entries_options_flow_handler ---- - -> This option is currently only available for built-in components. - -An integration that is configured via a config entry can expose options to the user to allow tweaking behavior of the integration, like which devices or locations should be integrated. - -Config Entry Options uses the [Data Flow Entry framework](data_entry_flow_index.md) to allow users to update a config entries options. Components that want to support config entry options will need to define a Options Flow Handler. - -## Options support - -For an integration to support options it needs to have an `async_get_options_flow` method in its config flow handler. Calling it will return an instance of the components options flow handler. - -```python -@staticmethod -@callback -def async_get_options_flow(config, options): - return OptionsFlowHandler(config, options) -``` - -## Flow handler - -The Flow handler works just like the config flow handler, except that the first step in the flow will always be `async_step_init`. - -```python -class OptionsFlowHandler(data_entry_flow.FlowHandler): - def __init__(self, config, options): -``` - -## Signal updates - -If the component should act on updated options, you can register an update listener to the config entry that will be called when the entry is updated. - -```python -entry.add_update_listener(update_listener) -``` - -The Listener shall be an async function that takes the same input as async_setup_entry. Options can then be accessed from `entry.options`. - -```python -async def update_listener(hass, entry): -``` - diff --git a/website/versioned_docs/version-0.91.2/creating_component_code_review.md b/website/versioned_docs/version-0.91.2/creating_component_code_review.md deleted file mode 100644 index d6997967..00000000 --- a/website/versioned_docs/version-0.91.2/creating_component_code_review.md +++ /dev/null @@ -1,70 +0,0 @@ ---- -title: Checklist for creating a component -sidebar_label: Component Checklist -id: version-0.91.2-creating_component_code_review -original_id: creating_component_code_review ---- - -A checklist of things to do when you're adding a new component. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on components level - -### 1. Requirements - - 1. Requirements have been added to [`manifest.json`](creating_integration_manifest.md). The `REQUIREMENTS` constant is deprecated. - 2. Requirement version should be pinned: `"requirements": ['phue==0.8.1']` - 3. We no longer want requirements hosted on GitHub. Please upload to PyPi. - 4. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Configuration - - 1. Voluptuous schema present for [configuration validation](development_validation.md) - 2. Default parameters specified in voluptuous schema, not in `setup(…)` - 3. Schema using as many generic config keys as possible from `homeassistant.const` - 4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`. - 5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation` - 6. Never depend on users adding things to `customize` to configure behavior inside your component. - -### 3. Component/platform communication - - 1. You can share data with your platforms by leveraging `hass.data[DOMAIN]`. - 2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`. - -### 4. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - - ```python - # bad - status = requests.get(url('/status')) - - # good - from phue import Bridge - bridge = Bridge(...) - status = bridge.status() - ``` - - [Tutorial on publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) - -### 5. Make your pull request as small as possible - -Keep a new integration to the minimum functionality needed for someone to get value out of the integration. This allows reviewers to sign off on smaller chunks of code one at a time, and lets us get your new integration/features in sooner. **Pull requests containing large code dumps will not be a priority for review and may be closed.** - -- Limit to a single platform -- Do not add features not needed to directly support the single platform (such as custom services) -- Do not mix clean-ups and new features in a single pull request. -- Do not solve several issues in a single pull request. -- Do not submit pull requests that depend on other work which is still unmerged. - -### 6. Event names -Prefix component event names with the domain name. For example, use `netatmo_person` instead of `person` for the `netatmo` component. - -### 7. Tests - -Strongly consider adding tests for your component to minimize future regressions. diff --git a/website/versioned_docs/version-0.91.2/creating_component_deps_and_reqs.md b/website/versioned_docs/version-0.91.2/creating_component_deps_and_reqs.md deleted file mode 100644 index 6f3fb119..00000000 --- a/website/versioned_docs/version-0.91.2/creating_component_deps_and_reqs.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: creating_component_deps_and_reqs -id: version-0.91.2-creating_component_deps_and_reqs -original_id: creating_component_deps_and_reqs ---- - -[This page has moved.](creating_integration_manifest.md) - - diff --git a/website/versioned_docs/version-0.91.2/creating_component_generic_discovery.md b/website/versioned_docs/version-0.91.2/creating_component_generic_discovery.md deleted file mode 100644 index 61011612..00000000 --- a/website/versioned_docs/version-0.91.2/creating_component_generic_discovery.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Integration with Multiple Platforms -sidebar_label: Multiple platforms -id: version-0.91.2-creating_component_generic_discovery -original_id: creating_component_generic_discovery ---- - -Most integrations consist of a single platform. And in that case, it's fine to just define that one platform. However, if you are going to add a second platform, you will want to centralize your connection logic. This is done inside the component (`__init__.py`). - -If your integration is configurable via `configuration.yaml`, it will cause the entry point of your configuration to change, as now users will need to set up your integration directly, and it is up to your integration to set up the platforms. - -## Loading platforms when configured via a config entry - -If your integration is set up via a config entry, you will need to forward the config entry to the appropriate integration to set up your platform. For more info, see the [config entry documentation](config_entries_index.md#for-platforms). - -## Loading platforms when configured via configuration.yaml - -If your integration is not using config entries, it will have to use our discovery helpers to set up its platforms. Note, this approach does not support unloading. - -To do this, you will need to use the `load_platform` and `async_load_platform` methods from the discovery helper. - - -- See also a [full example that implementing this logic](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_load_platform/) diff --git a/website/versioned_docs/version-0.91.2/creating_component_index.md b/website/versioned_docs/version-0.91.2/creating_component_index.md deleted file mode 100644 index 4e11eecd..00000000 --- a/website/versioned_docs/version-0.91.2/creating_component_index.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Creating a Minimal Component -sidebar_label: Minimal Component -id: version-0.91.2-creating_component_index -original_id: creating_component_index ---- - -Alright, you learned about the [manifest](creating_integration_manifest.md), so it's time to write your first code for your integration. AWESOME. Don't worry, we've tried hard to keep it as easy as possible. - -More extensive examples of integrations are available from [our example repository](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/). - -## The code - -Each component needs to have 2 basic parts: it needs to define a `DOMAIN` constant that contains the domain of the integration. The second part is that it needs to define a setup method that returns a boolean if the set up was successful. So let's take a look at how this looks: - -```python -DOMAIN = 'hello_state' - -def setup(hass, config): - hass.states.set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -And if you prefer an async component: - -```python -DOMAIN = 'hello_state' - -async def async_setup(hass, config): - hass.states.async_set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -That's it! If you load this, you will see a new state in the state machine. - -To load this, add `hello_state:` to your `configuration.yaml` file and create a file `/custom_components/hello_state/__init__.py` with the below code to test it locally. diff --git a/website/versioned_docs/version-0.91.2/creating_integration_file_structure.md b/website/versioned_docs/version-0.91.2/creating_integration_file_structure.md deleted file mode 100644 index 96dd348e..00000000 --- a/website/versioned_docs/version-0.91.2/creating_integration_file_structure.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Integration File Structure -sidebar_label: File Structure -id: version-0.91.2-creating_integration_file_structure -original_id: creating_integration_file_structure ---- - -Each integration is stored inside a directory named after the integration domain. The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. So all files for this integration are in the folder `mobile_app/`. - -The bare minimum content of this folder looks like this: - - - `manifest.json`: The manifest file describes the integration and its dependencies. [More info](creating_integration_manifest.md) - - `__init__.py`: The component file. If the integration only offers a platform, you can keep this file limited to a docstring introducing the integration `"""The Mobile App integration."""`. - -## Integrating devices - `light.py`, `switch.py` etc - -If your integration is going to integrate one or more devices, you will need to do this by creating a platform that interacts with an entity integration. For example, if you want to represent a light device inside Home Assistant, you will create `light.py`, which will contain a light platform for the light integration. - -- More info on [available entity integrations](entity_index.md). -- More info on [creating platforms](creating_platform_index.md). - -## Integrating services - `services.yaml` - -If your integration is going to register services, it will need to provide a description of the available services. The description is stored in `services.yaml`. [More information about `services.yaml`.](dev_101_services.md) - -## Where Home Assistant looks for integrations - -Home Assistant will look for an integration when it sees the domain referenced in the config file (i.e. `mobile_app:`) or if it is a dependency of another integration. Home Assistant will look at the following locations: - - * `/custom_components/` - * `homeassistant/components/` (built-in integrations) - -You can override a built-in integration by having an integration with the same domain in your `config/custom_components` folder. Note that overriding built-in components is not recommended as you will no longer get updates. It is recommended to pick a unique name. diff --git a/website/versioned_docs/version-0.91.2/creating_integration_manifest.md b/website/versioned_docs/version-0.91.2/creating_integration_manifest.md deleted file mode 100644 index b3004a1a..00000000 --- a/website/versioned_docs/version-0.91.2/creating_integration_manifest.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: Integration Manifest -sidebar_label: Manifest -id: version-0.91.2-creating_integration_manifest -original_id: creating_integration_manifest ---- - -Each integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, including for custom components. - -```json -{ - "domain": "hue", - "name": "Philips Hue", - "documentation": "https://www.home-assistant.io/components/hue", - "dependencies": ["mqtt"], - "codeowners": ["@balloob"], - "requirements": ["aiohue==1.9.1"] -} -``` - -Or a minimal example that you can copy into your project: - -```json -{ - "domain": "your_domain_name", - "name": "Your Intgration", - "documentation": "https://www.example.com", - "dependencies": [], - "codeowners": [], - "requirements": [] -} -``` - -## Domain - -The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. - -## Name - -The name of the integration. - -## Documentation - -The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/` - -## Dependencies - -Dependencies are other Home Assistant integrations that you want Home Assistant to set up successfully prior to the integration being loaded. This can be necessary in case you want to offer functionality from that other integration, like using webhooks or an MQTT connection. - -## Code Owners - -GitHub usernames or team names of people that are responsible for this integration. You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included. - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you running in a virtual environment. This will make sure that all requirements are present at startup. If steps fail, like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is a list of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v0.6.12: `['pychromecast==0.6.12']`. - -> Because of how Home Assistant installs requirements on demand, actual Python imports of your requirements should be done inside functions instead of at the root level of your Python files. - -### Custom requirements during development & testing - -During the development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using `pychromecast` as an example: - -```bash -pip install pychromecast==0.6.13 --target ~/.homeassistant/deps -hass --skip-pip -``` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is specified in `requirements`. - -If you need to make changes to a requirement to support your component, it's also possible to install a development version of the requirement using `pip install -e`: - -```bash -git clone https://github.com/balloob/pychromecast.git -pip install ./pychromecast -hass --skip-pip -``` diff --git a/website/versioned_docs/version-0.91.2/creating_platform_code_review.md b/website/versioned_docs/version-0.91.2/creating_platform_code_review.md deleted file mode 100644 index d04996cc..00000000 --- a/website/versioned_docs/version-0.91.2/creating_platform_code_review.md +++ /dev/null @@ -1,93 +0,0 @@ ---- -title: Checklist for creating a platform -sidebar_label: Platform Checklist -id: version-0.91.2-creating_platform_code_review -original_id: creating_platform_code_review ---- - -A checklist of things to do when you're adding a new platform. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on platform level - * Use `CONF_MONITORED_CONDITIONS` instead of `CONF_MONITORED_VARIABLES` - -### 1. Requirements - - 1. Requirements have been added to [`manifest.json`](creating_integration_manifest.md). The `REQUIREMENTS` constant is deprecated. - 2. Requirement version should be pinned: `"requirements": ['phue==0.8.1']` - 3. We no longer want requirements hosted on GitHub. Please upload to PyPi. - 4. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly. - -### 2. Dependencies - - 1. If you depend on a component for the connection, add it to your dependencies in [`manifest.json`](creating_integration_manifest.md): `"dependencies": ['nest']`. The `DEPENDENCIES` constant is deprecated. - -### 3. Configuration - - 1. Voluptuous schema present for [configuration validation](development_validation.md) - 2. Voluptuous schema extends schema from component
(e.g., `hue.light.PLATFORM_SCHEMA` extends `light.PLATFORM_SCHEMA`) - 3. Default parameters specified in voluptuous schema, not in `setup_platform(...)` - 4. Your `PLATFORM_SCHEMA` should use as many generic config keys as possible from `homeassistant.const` - 5. Never depend on users adding things to `customize` to configure behavior inside your platform. - -```python -import voluptuous as vol - -from homeassistant.const import CONF_FILENAME, CONF_HOST -from homeassistant.components.light import PLATFORM_SCHEMA -import homeassistant.helpers.config_validation as cv - -CONF_ALLOW_UNREACHABLE = 'allow_unreachable' -DEFAULT_UNREACHABLE = False - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_ALLOW_UNREACHABLE, - default=DEFAULT_UNREACHABLE): cv.boolean, - vol.Optional(CONF_FILENAME): cv.string, -}) -``` - -### 4. Setup Platform - - 1. Verify that the passed in configuration (user/pass/host etc.) works. - 2. Group your calls to `add_devices` if possible. - 3. If the platform adds extra services, the format should be `.`. So if your integration's domain is "awesome_sauce" and you are making a light platform, you would register services under the `awesome_sauce` domain. Make sure that your services [verify permissions](auth_permissions.md#checking-permissions). - -### 5. Entity - - 1. Extend the entity from the integration you're building a platform for. - - ```python - from homeassistant.components.light import Light - - class HueLight(Light): - ... - ``` - - 2. Avoid passing in `hass` as a parameter to the entity. When the entity has been added to Home Assistant, `hass` will be set on the entity when the entity is added to Home Assistant. This means you can access `hass` as `self.hass` inside the entity. - 3. Do not call `update()` in constructor, use `add_entities(devices, True)` instead. - 4. Do not do any I/O inside properties. Cache values inside `update()` instead. - 5. When dealing with time, state and/or attributes should not contain relative time since something happened. Instead, it should store UTC timestamps. - 6. Leverage the [entity lifecycle callbacks](entity_index.md#lifecycle-hooks) to attach event listeners or clean up connections. - -### 6. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - - ```python - # bad - status = requests.get(url('/status')) - - # good - from phue import Bridge - bridge = Bridge(...) - status = bridge.status() - ``` - - [Tutorial on publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) diff --git a/website/versioned_docs/version-0.91.2/creating_platform_example_light.md b/website/versioned_docs/version-0.91.2/creating_platform_example_light.md deleted file mode 100644 index aedca662..00000000 --- a/website/versioned_docs/version-0.91.2/creating_platform_example_light.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: creating_platform_example_light -id: version-0.91.2-creating_platform_example_light -original_id: creating_platform_example_light ---- - -[This page has moved.](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_light) - - diff --git a/website/versioned_docs/version-0.91.2/creating_platform_example_sensor.md b/website/versioned_docs/version-0.91.2/creating_platform_example_sensor.md deleted file mode 100644 index e4bb3da9..00000000 --- a/website/versioned_docs/version-0.91.2/creating_platform_example_sensor.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: creating_platform_example_sensor -id: version-0.91.2-creating_platform_example_sensor -original_id: creating_platform_example_sensor ---- - -[This page has moved.](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_sensor) - - diff --git a/website/versioned_docs/version-0.91.2/creating_platform_index.md b/website/versioned_docs/version-0.91.2/creating_platform_index.md deleted file mode 100644 index b856bf69..00000000 --- a/website/versioned_docs/version-0.91.2/creating_platform_index.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Integration Platforms -sidebar_label: Platforms -id: version-0.91.2-creating_platform_index -original_id: creating_platform_index ---- - -Home Assistant has various built-in integrations that abstract device types. There are [lights](entity_light.md), [switches](entity_switch.md), [covers](entity_cover.md), [climate devices](entity_climate.md), and [many more](entity_index.md). Your integration can hook into these integrations by creating a platform. You will need a platform for each integration that you are integrating with. - -To create a platform, you will need to create a file with the domain name of the integration that you are building a platform for. So if you are building a light, you will add a new file `light.py` to your integration folder. - -We have created two example integrations that should give you a look at how this works: - - - [Example sensor platform](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_sensor/): hello world of platforms. - - [Example light platform](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_light/): showing best practices. - -### Interfacing with devices - -One Home Assistant rule is that the integration should never interface directly with devices. Instead, it should interact with a third-party Python 3 library. This way, Home Assistant can share code with the Python community and keep the project maintainable. - -Once you have your Python library ready and published to PyPi, add it to the [manifest](creating_integration_manifest.md). It will now be time to implement the Entity base class that is provided by the integration that you are creating a platform for. - -Find your integration at the [entity index](entity_index.md) to see what methods and properties are available to implement. diff --git a/website/versioned_docs/version-0.91.2/dev_101_services.md b/website/versioned_docs/version-0.91.2/dev_101_services.md deleted file mode 100644 index 2191a571..00000000 --- a/website/versioned_docs/version-0.91.2/dev_101_services.md +++ /dev/null @@ -1,78 +0,0 @@ ---- -title: Integration Services -sidebar_label: Custom Services -id: version-0.91.2-dev_101_services -original_id: dev_101_services ---- - -Home Assistant provides ready-made services for a lot of things, but it doesn't always cover everything. Instead of trying to change Home Assistant, it is preferred to add it as a service under your own integration first. Once we see a pattern in these services, we can talk about generalizing them. - -This is a simple "hello world" example to show the basics of registering a service. To use this example, create the file `/custom_components/hello_service/__init__.py` and copy the below example code. - -Services can be called from automations and from the service "Developer tools" in the frontend. - -```python -DOMAIN = 'hello_service' - -ATTR_NAME = 'name' -DEFAULT_NAME = 'World' - - -def setup(hass, config): - """Set up is called when Home Assistant is loading our component.""" - - def handle_hello(call): - """Handle the service call.""" - name = call.data.get(ATTR_NAME, DEFAULT_NAME) - - hass.states.set('hello_service.hello', name) - - hass.services.register(DOMAIN, 'hello', handle_hello) - - # Return boolean to indicate that initialization was successfully. - return True -``` - -Load the integration by adding the following to your `configuration.yaml`. When your component is loaded, a new service should be available to call. - -```yaml -# configuration.yaml entry -hello_service: -``` - -Open the frontend and in the sidebar, click the first icon in the developer tool section. This will open the Call Service developer tool. On the right, find your service and click on it. This will automatically fill in the correct values. - -Pressing "Call Service" will now call your service without any parameters. This will cause your service to create a state with the default name 'World'. If you want to specify the name, you have to specify parameters. Add the following JSON as Service Data and press "Call Service again". - -```json -{ - "name": "Planet" -} -``` - -The service will now overwrite the previous state with "Planet". - -## Service descriptions - -Adding services is only useful if users know about them. In Home Assistant we use a `services.yaml` as part of your integration to describe the services. - -Services are published under the domain name of your integration, so in `services.yaml` we only use the service name as the base key. - -```yaml -# Example services.yaml entry - -set_speed: - # Description of the service - description: Sets fan speed. - # Different fields that your service accepts - fields: - # Key of the field - entity_id: - # Description of the field - description: Name(s) of the entities to set - # Example value that can be passed for this field - example: 'fan.living_room' - speed: - description: Speed setting - example: 'low' -``` diff --git a/website/versioned_docs/version-0.91.2/dev_101_states.md b/website/versioned_docs/version-0.91.2/dev_101_states.md deleted file mode 100644 index 909abb67..00000000 --- a/website/versioned_docs/version-0.91.2/dev_101_states.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Using States -id: version-0.91.2-dev_101_states -original_id: dev_101_states ---- - -Home Assistant keeps track of the states of entities in a state machine. The state machine has very few requirements: - - - Each state is related to an entity identified by an entity id. This id is made up of a domain and an object id. For example `light.kitchen_ceiling`. You can make up any combination of domain and object id, even overwriting existing states. - - Each state has a primary attribute that describes the state of the entity. In the case of a light this could be for example "on" and "off". You can store anything you want in the state, as long as it's a string (will be converted if it's not). - - You can store more information about an entity by setting attributes. Attributes is a dictionary that can contain any data that you want. The only requirement is that it's JSON serializable, so you're limited to numbers, strings, dictionaries and lists. - -[Description of the state object.](https://www.home-assistant.io/docs/configuration/state_object/) - -## Using states in your component - -This is a simple tutorial/example on how to create and set states. We will do our work in a component called "hello_state". The purpose of this component is to display a given text in the frontend. - -To get started, create the file `/custom_components/hello_state.py` and copy the below example code. - -```python -""" -Support for showing text in the frontend. - -For more details about this component, please refer to the documentation at -https://home-assistant.io/cookbook/python_component_basic_state/ -""" -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = 'hello_state' - -def setup(hass, config): - """Setup the Hello State component. """ - _LOGGER.info("The 'hello state' component is ready!") - - return True -``` - -1. In the file header we decided to add some details: A short description and the link to the documentation. -2. We want to do some logging. This means that we import the Python logging module and create an alias. -3. The component name is equal to the domain name. -4. The `setup` function will take care of the initialization of our component. - The component will only write a log message. Keep in mind for later that you have several options for the severity: - - - `_LOGGER.info(msg)` - - `_LOGGER.warning(msg)` - - `_LOGGER.error(msg)` - - `_LOGGER.critical(msg)` - - `_LOGGER.exception(msg)` - -5. We return `True` if everything is ok. - -Add the component to your `configuration.yaml` file. - -```yaml -hello_state: -``` - -After a start or a restart of Home Assistant the component will create an entry in the log. - -```bash -16-03-12 14:16:42 INFO (MainThread) [custom_components.hello_state] The 'hello state' component is ready! -``` - -The next step is the introduction of configuration options. A user can pass configuration options to our component via `configuration.yaml`. To use them we'll use the passed in `config` variable to our `setup` method. - -```python -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = 'hello_state' - -CONF_TEXT = 'text' -DEFAULT_TEXT = 'No text!' - -def setup(hass, config): - """Set up the Hello State component. """ - # Get the text from the configuration. Use DEFAULT_TEXT if no name is provided. - text = config[DOMAIN].get(CONF_TEXT, DEFAULT_TEXT) - - # States are in the format DOMAIN.OBJECT_ID - hass.states.set('hello_state.Hello_State', text) - - return True -``` - -To use the latest feature of our component, update the entry in your `configuration.yaml` file. - -```yaml -hello_state: - text: 'Hello, World!' -``` - -Thanks to `DEFAULT_TEXT` variable the component will launch even if no `text:` field is used in the `configuration.yaml` file. Quite often there are variables which are required. It's important to check if all mandatory configuration variables are provided. If not, the setup should fail. We will use `voluptuous` as a helper to achieve this. The next listing shows the essential parts. - -```python -import voluptuous as vol - -import homeassistant.helpers.config_validation as cv - -CONFIG_SCHEMA = vol.Schema({ - DOMAIN: vol.Schema({ - vol.Required(CONF_TEXT): cv.string, - }) -}, extra=vol.ALLOW_EXTRA) -``` - -Now, when `text:` is missing from the config, Home Assistant will alert the user and not setup your component. - -After a start or a restart of Home Assistant the component will be visible in the frontend if the `configuration.yaml` file is up-to-date. - -

- -

- -In order to expose attributes for a platform, you will need to define a property called `device_state_attributes` on the entity class, which will return a dictionary of attributes: - -``` -@property -def device_state_attributes(self): - """Return device specific state attributes.""" - return self._attributes -``` - -> Entities also have a similar property `state_attributes`, which normally doesn't need to be defined by new platforms. This property is used by base components to add standard sets of attributes to a state. Example: The light component uses `state_attributes` to add brightness to the state dictionary. If you are designing a new component, you should define `state_attributes` instead. - -To get your component included in the Home Assistant releases, follow the steps described in the [Submit your work](development_submitting.md) section. Basically you only need to move your component in the `homeassistant/component/` directory of your fork and create a Pull Request. diff --git a/website/versioned_docs/version-0.91.2/development_checklist.md b/website/versioned_docs/version-0.91.2/development_checklist.md deleted file mode 100644 index a8a4a811..00000000 --- a/website/versioned_docs/version-0.91.2/development_checklist.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Development Checklist -sidebar_label: Introduction -id: version-0.91.2-development_checklist -original_id: development_checklist ---- - - -Before you commit any changes, check your work against these requirements: - -- All communication to external devices or services must be wrapped in an external Python library hosted on [pypi](https://pypi.python.org/pypi). -- New dependencies are added to `requirements_all.txt` (if applicable), using `script/gen_requirements_all.py` -- New codeowners are added to `CODEOWNERS` (if applicable), using `script/manifest/codeowners.py` -- The `.coveragerc` file is updated to exclude your platform if there are no tests available or your new code uses a third-party library for communication with the device, service, or sensor -- Documentation is developed for [home-assistant.io](https://home-assistant.io/) - * Visit the [website documentation](https://www.home-assistant.io/developers/documentation/) for more information about contributing to [home-assistant.io](https://github.com/home-assistant/home-assistant.github.io). -- All dependencies are only imported inside functions that use them. diff --git a/website/versioned_docs/version-0.91.2/development_guidelines.md b/website/versioned_docs/version-0.91.2/development_guidelines.md deleted file mode 100644 index 702706e3..00000000 --- a/website/versioned_docs/version-0.91.2/development_guidelines.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: Style guidelines -id: version-0.91.2-development_guidelines -original_id: development_guidelines ---- - -Home Assistant enforces strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. We automatically test every pull request as part of the linting process. - -Summary of the most relevant points: - -- Line length is limited to 79 characters (see below). -- Use 4 spaces per indentation level. We don't use tabs. -- Comments should be full sentences and end with a period. -- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered. -- Constants and the content of lists and dictionaries should be in alphabetical order. -- Avoid trailing whitespace but surround binary operators with a single space. -- Line separator should be set to `LF`. - -The maximum line length comes directly from the [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/#maximum-line-length), and is also used by the Python standard library. All code must pass these linting checks, and no exceptions will be made. There have already been numerous requests to increase the maximum line length, but after evaluating the options, the Home Assistant maintainers have decided to stay at 79 characters. This decision is final. - -Those points may require that you adjust your IDE or editor settings. - -## Our recommendations - -For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code unified. - -### Quotes - -Use single quotes `'` for single word and `"` for multiple words or sentences. - -```python -ATTR_WATERLEVEL = 'level' -CONF_ATTRIBUTION = "Data provided by the WUnderground weather service" -SENSOR_TYPES = { - 'alerts': ['Alerts', None], -} -``` - -### File headers - -The docstring in the file header should describe what the file is about. - -```python -"""Support for MQTT lights.""" -``` - -### Log messages - -There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. Try to avoid brackets and additional quotes around the output to make it easier for users to parse the log. A widely style is shown below but you are free to compose the messages as you like. - -```python -_LOGGER.error("No route to device: %s", self._resource) -``` - -```bash -2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18 -``` - -Don't print out wrong API keys, tokens, usernames, or passwords. -Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` in anything else. - -### Ordering of imports - -Instead of order the imports manually, use [`isort`](https://github.com/timothycrosley/isort). - -```bash -$ pip3 install isort -$ isort homeassistant/components/sensor/fixer.py -``` - -### Use new style string formatting - -Prefer [new style string formatting](https://www.python.org/dev/peps/pep-3101/) over old. - -```python -"{} {}".format('New', 'style') -"%s %s" % ('Old', 'style') -``` - -Except when doing logging here the format is: - -```python -_LOGGER.info("Can't connect to the webservice %s at %s", string1, string2) -``` diff --git a/website/versioned_docs/version-0.91.2/development_index.md b/website/versioned_docs/version-0.91.2/development_index.md deleted file mode 100644 index 5cc14af0..00000000 --- a/website/versioned_docs/version-0.91.2/development_index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: Starting with Development -sidebar_label: Introduction -id: version-0.91.2-development_index -original_id: development_index ---- - -Home Assistant is built from the ground up to be easily extensible using integrations. In this section, we're focusing on how to develop integrations. - -Before you start, make sure that you have read up on the [Home Assistant architecture](architecture_index.md) so that you are familiar with the concepts that make up Home Assistant. - -If you run into trouble following this documentation, don't hesitate to join our #devs_backend channel on [Discord](https://www.home-assistant.io/join-chat/). - diff --git a/website/versioned_docs/version-0.91.2/development_validation.md b/website/versioned_docs/version-0.91.2/development_validation.md deleted file mode 100644 index 61dc79b3..00000000 --- a/website/versioned_docs/version-0.91.2/development_validation.md +++ /dev/null @@ -1,82 +0,0 @@ ---- -title: Validate the input -id: version-0.91.2-development_validation -original_id: development_validation ---- - -The `configuration.yaml` file contains the configuration options for components and platforms. We use [voluptuous](https://pypi.python.org/pypi/voluptuous) to make sure that the configuration provided by the user is valid. Some entries are optional or could be required to set up a platform or a component. Others must be a defined type or from an already-defined list. - -We test the configuration to ensure that users have a great experience and minimize notifications if something is wrong with a platform or component setup before Home Assistant runs. - -Besides [voluptuous](https://pypi.python.org/pypi/voluptuous) default types, many custom types are available. For an overview, take a look at the [config_validation.py](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/config_validation.py) helper. - -- Types: `string`, `byte`, and `boolean` -- Entity ID: `entity_id` and `entity_ids` -- Numbers: `small_float` and `positive_int` -- Time: `time`, `time_zone` -- Misc: `template`, `slug`, `temperature_unit`, `latitude`, `longitude`, `isfile`, `sun_event`, `ensure_list`, `port`, `url`, and `icon` - -To validate platforms using [MQTT](https://www.home-assistant.io/components/mqtt/), `valid_subscribe_topic` and `valid_publish_topic` are available. - -Some things to keep in mind: - -- Use the constants defined in `const.py` -- Import `PLATFORM_SCHEMA` from the integration you are integrating with and extend it. -- Preferred order is `required` first and `optional` second -- Default values for optional configuration keys need to be valid values. Don't use a default which is `None` like `vol.Optional(CONF_SOMETHING, default=None): cv.string`, set the default to `default=''` if required. - -### Snippets - -This section contains snippets for the validation we use. - -#### Default name - -It's common to set a default for a sensor if the user doesn't provide a name to use. - -```python -DEFAULT_NAME = 'Sensor name' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, -``` - -#### Limit the values - -You might want to limit the user's input to a couple of options. - -```python -DEFAULT_METHOD = 'GET' - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): vol.In(['POST', 'GET']), -``` - -#### Port - -All port numbers are from a range of 1 to 65535. - -```python -DEFAULT_PORT = 993 - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port, -``` - -#### Lists - -If a sensor has a pre-defined list of available options, test to make sure the configuration entry matches the list. - -```python -SENSOR_TYPES = { - 'article_cache': ('Article Cache', 'MB'), - 'average_download_rate': ('Average Speed', 'MB/s'), -} - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - ... - vol.Optional(CONF_MONITORED_VARIABLES, default=[]): - vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]), -``` diff --git a/website/versioned_docs/version-0.91.2/entity_sensor.md b/website/versioned_docs/version-0.91.2/entity_sensor.md deleted file mode 100644 index 50dad0d8..00000000 --- a/website/versioned_docs/version-0.91.2/entity_sensor.md +++ /dev/null @@ -1,33 +0,0 @@ ---- -title: Sensor Entity -sidebar_label: Sensor -id: version-0.91.2-entity_sensor -original_id: entity_sensor ---- - -A sensor is a read-only entity that provides some information. Information has a value and optionally, a unit of measurement. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| state | string | **Required** | The value of the sensor. -| unit_of_measurement | string | `None` | The unit of measurement that the sensor is expressed in. -| device_class | string | `None` | Type of sensor. - -### Available device classes - -If specifying a device class, your sensor entity will need to also return the correct unit of measurement. - -| Type | Unit | Description -| ---- | ---- | ----------- -| battery | % | % of battery that is left. -| humidity | % | % of humidity in the air. -| illuminance | lx/lm | Light level. -| signal_strength | dB/dBm | Signal strength. -| temperature | °C/°F | Temperature. -| timestamp | ISO8601 | Timestamp. -| power | W,kW | Power. -| pressure | hPa,mbar | Pressure. diff --git a/website/versioned_docs/version-0.91.2/internationalization_translation.md b/website/versioned_docs/version-0.91.2/internationalization_translation.md deleted file mode 100644 index 13a32f73..00000000 --- a/website/versioned_docs/version-0.91.2/internationalization_translation.md +++ /dev/null @@ -1,42 +0,0 @@ ---- -title: Translation -id: version-0.91.2-internationalization_translation -original_id: internationalization_translation ---- - -Translations for Home Assistant are managed through [Lokalise](https://lokalise.co/), an online translation management tool. Our translations are split between two projects, a backend project for platform-specific translations, and a frontend project for UI translations. Click the links below to join both projects! Even if your language is completely translated, extra proofreading is a big help! Please feel free to review the existing translations, and vote for alternatives that might be more appropriate. - -- [Join the frontend translation team](https://lokalise.co/signup/3420425759f6d6d241f598.13594006/all/) -- [Join the backend translation team](https://lokalise.co/signup/130246255a974bd3b5e8a1.51616605/all/) -- [Join the iOS translation team](https://lokalise.co/signup/834452985a05254348aee2.46389241/all/) - -For more information about the translation workflow, please see the [Lokalise translation workflow documents](https://docs.lokalise.co/category/iOzEuQPS53-for-team-leads-and-translators). - -> The translation of the Home Assistant frontend is still a work in progress. More phrases will be available for translation soon. - -## Translation placeholders - -Some translation strings will contain special placeholders that will be replaced later. Placeholders shown in square brackets `[]` are [Lokalise key references](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing). These are primarily used to link translation strings that will be duplicated. Different languages may not have the same duplicates as English, and are welcome to link duplicate translations that are not linked in English. Placeholders shown in curly brackets `{}` are [translation arguments](https://formatjs.io/guides/message-syntax/) that will be replaced with a live value when Home Assistant is running. Any translation argument placeholders present in the original string must be included in the translated string. These may include special syntax for defining plurals or other replacement rules. The linked format.js guide explains the syntax for adding plural definitions and other rules. - -## Rules -1. Only native speakers should submit translations. -2. Stick to [Material Design guidelines](https://material.io/guidelines/style/writing.html). -3. Don't translate or change proper nouns like `Home Assistant`, `Hass.io` or `Hue`. -4. For a region specific translation, keys that will be the same as the base translation should be filled with `[VOID]`. These will be replaced during our translation build process. -5. Translations under the `state_badge` keys will be used for the notification badge display. These translations should be short enough to fit in the badge label without overflowing. This can be tested in the Home Assistant UI either by editing the label text with your browsers development tools, or by using the States states dev tool icon developer tool in the Home Assistant UI. In the UI, enter a new entity ID (`device_tracker.test`), and enter the text you want to test in state. -6. If text will be duplicated across different translation keys, make use of the Lokalise key reference feature where possible. The base translation provides examples of this underneath the `states` translations. Please see the [Lokalise key referencing](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing) documentation for more details. - -## Adding a new language -If your language is not listed you can request it at [GitHub](https://github.com/home-assistant/home-assistant-polymer/issues/new). Please provide both the English name and the native name for your language. For example: -``` -English Name: German -Native Name: Deutsch -``` - -> Region specific translations (`en-US`, `fr-CA`) will only be included if translations for that region need to differ from the base language translation. - -### Maintainer steps to add a new language -1. Language tags have to follow [BCP 47](https://tools.ietf.org/html/bcp47). A list of most language tags can be found here: [IANA sutbtag registry](http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry). Examples: `fr`, `fr-CA`, `zh-Hans`. Only include the country code if country specific overrides are being included, and the base language is already translated. -2. Add the language tag and native name in `src/translations/translationMetadata.json`. Examples: "Français", "Français (CA)" -3. Add the new language in Lokalize. -Note: Sometimes you have to change the tag in Lokalise (Language -> Language settings -> custom ISO code). diff --git a/website/versioned_docs/version-0.91.2/maintenance.md b/website/versioned_docs/version-0.91.2/maintenance.md deleted file mode 100644 index 0be7c270..00000000 --- a/website/versioned_docs/version-0.91.2/maintenance.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -title: Maintenance -id: version-0.91.2-maintenance -original_id: maintenance ---- - -This page documents a couple of points for maintaining the Home Assistant code. Most of the tasks don't need to be performed on a regular base thus the steps, used tools, or details are preserved here. - -## Source code - -### Line separator - -People are using various operating systems to develop components and platforms for Home Assistant. This could lead to different line endings on file. We prefer `LN`. Especially Microsoft Windows tools tend to use `CRLF`. - -```bash -$ find homeassistant -name "*.py" -exec file {} \; | grep BOM -$ find homeassistant -name "*.py" -exec file {} \; | grep CRLF -``` - -To fix the line separator, use `dos2unix` or `sed`. - -```bash -$ dos2unix homeassistant/components/notify/kodi.py -``` - -### File permissions - -Most files don't need to the be executable. `0644` is fine. - -### Dependencies - -A lot of components and platforms depends on third-party Python modules. The dependencies which are stored in the `requirements_*.txt` files are tracked by [Requires.io](https://requires.io/github/home-assistant/home-assistant/requirements/?branch=dev). - -If you update the requirements of a component/platform by updating `manifest.json`, run the provided script to update the `requirements_*.txt` file(s). - -```bash -$ script/gen_requirements_all.py -``` - -Start a test run of Home Assistant. If that was successful, include all files in a Pull Request. Add a short summary of the changes, a sample configuration entry, details about the tests you performed to ensure the update works, and other useful information to the description. - - -## Documentation - -- Merge `current` into `next` on a regular base. -- Optimize the images. - diff --git a/website/versioned_docs/version-0.92.0/app_integration_setup.md b/website/versioned_docs/version-0.92.0/app_integration_setup.md deleted file mode 100644 index 5fe05160..00000000 --- a/website/versioned_docs/version-0.92.0/app_integration_setup.md +++ /dev/null @@ -1,85 +0,0 @@ ---- -title: Connecting to an instance -id: version-0.92.0-app_integration_setup -original_id: app_integration_setup ---- - -When a user first opens the app, they will need to connect to their local instance to authenticate and register the device. - -## Authenticating the user - -The local instance can be discovered if Home Assistant has the [zeroconf component] configured by searching for `_home-assistant._tcp.local.`. If not configured, the user will need to be asked for the local address of their instance. - -When the address of the instance is known, the app will ask the user to authenticate via [OAuth2 with Home Assistant]. Home Assistant uses IndieAuth, which means that to be able to redirect to a url that triggers your app, you need to take some extra steps. Make sure to read the last paragraph of the "Clients" section thoroughly. - -[zeroconf component]: https://www.home-assistant.io/components/zeroconf -[OAuth2 with Home Assistant]: auth_api.md - -## Registering the device - -_This requires Home Assistant 0.90 or later._ - -Home Assistant has a `mobile_app` component that allows applications to register themselves and interact with the instance. This is a generic component to handle most common mobile application tasks. This component is extendable with custom interactions if your app needs more types of interactions than are offered by this component. - -Once you have tokens to authenticate as a user, it's time to register the app with the mobile app component in Home Assistant. - -### Getting Ready - -First, you must ensure that the `mobile_app` component is loaded. There are two ways to do this: - -- You can publish a Zeroconf/Bonjour record `_hass-mobile-app._tcp.local.` to trigger the automatic load of the `mobile_app` component. You should wait at least 60 seconds after publishing the record before continuing. -- You can ask the user to add `mobile_app` to their configuration.yaml and restart Home Assistant. If the user already has `default_config` in their configuration, then `mobile_app` will have been already loaded. - -You can confirm the `mobile_app` component has been loaded by checking the `components` array of the [`/api/config` REST API call](external_api_rest.md#get-api-config). If you continue to device registration and receive a 404 status code, then it most likely hasn't been loaded yet. - -### Registering the device - -To register the device, make an authenticated POST request to `/api/mobile_app/registrations`. [More info on making authenticated requests.](auth_api.md#making-authenticated-requests) - -Example payload to send to the registration endpoint: - -```json -{ - "app_id": "awesome_home", - "app_name": "Awesome Home", - "app_version": "1.2.0", - "device_name": "Robbies iPhone", - "manufacturer": "Apple, Inc.", - "model": "iPhone X", - "os_version": "iOS 10.12", - "supports_encryption": true, - "app_data": { - "push_notification_key": "abcdef", - } -} -``` - -| Key | Required | Type | Description | -| --- | -------- | ---- | ----------- | -| `app_id` | V | string | A unique identifier for this app. -| `app_name` | V | string | Name of the mobile app. -| `app_version` | V | string | Version of the mobile app. -| `device_name` | V | string | Name of the device running the app. -| `manufacturer` | V | string | The manufacturer of the device running the app. -| `model` | V | string | The model of the device running the app. -| `os_version` | V | string | The OS version of the device running the app. -| `supports_encryption` | V | bool | If the app supports encryption. See also the [encryption section](#encryption). -| `app_data` | | Dict | App data can be used if the app has a supporting component that extends `mobile_app` functionality. - -When you get a 200 response, the mobile app is registered with Home Assistant. The response is a JSON document and will contain the URLs on how to interact with the Home Assistant instance. You should permanently store this information. - -```json -{ - "cloudhook_url": "https://hooks.nabu.casa/randomlongstring123", - "remote_ui_url": "https://randomlongstring123.ui.nabu.casa", - "secret": "qwerty", - "webhook_id": "abcdefgh" -} -``` - -| Key | Type | Description -| --- | ---- | ----------- -| `cloudhook_url` | string | The cloudhook URL provided by Home Assistant Cloud. Only will be provided if user is actively subscribed to Nabu Casa. -| `remote_ui_url` | string | The remote UI URL provided by Home Assistant Cloud. Only will be provided if user is actively subscribed to Nabu Casa. -| `secret` | string | The secret to use for encrypted communication. Will only be included if encryption is supported by both the app and the Home Assistant instance. [More info](app_integration_sending_data.md#implementing-encryption). -| `webhook_id` | string | The webhook ID that can be used to send data back. diff --git a/website/versioned_docs/version-0.92.0/auth_auth_module.md b/website/versioned_docs/version-0.92.0/auth_auth_module.md deleted file mode 100644 index cc68d307..00000000 --- a/website/versioned_docs/version-0.92.0/auth_auth_module.md +++ /dev/null @@ -1,67 +0,0 @@ ---- -title: Multi-factor Authentication Modules -id: version-0.92.0-auth_auth_module -original_id: auth_auth_module ---- - -Multi-factor Authentication Modules are used in conjunction with [Authentication Provider](auth_auth_provider.html) to provide a fully configurable authentication framework. Each MFA module may provide one multi-factor authentication function. User can enable multiple mfa modules, but can only select one module in login process. - -## Defining an mfa auth module - -> We currently only support built-in mfa auth modules. Support for custom auth modules might arrive in the future. - -Multi-factor Auth modules are defined in `homeassistant/auth/mfa_modules/.py`. The auth module will need to provide an implementation of the `MultiFactorAuthModule` class. - -For an example of a fully implemented auth module, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth/mfa_modules/insecure_example.py). - -Multi-factor Auth modules shall extend the following methods of `MultiFactorAuthModule` class. - -| method | Required | Description -| ------ | -------- | ----------- -| `@property def input_schema(self)` | Yes | Return a schema defined the user input form. -| `async def async_setup_flow(self, user_id)` | Yes | Return a SetupFlow to handle the setup workflow. -| `async def async_setup_user(self, user_id, setup_data)` | Yes | Set up user for use this auth module. -| `async def async_depose_user(self, user_id)` | Yes | Remove user information from this auth module. -| `async def async_is_user_setup(self, user_id)` | Yes | Return whether user is set up. -| `async def async_validate(self, user_id, user_input)` | Yes | Given a user_id and user input, return validation result. -| `async def async_initialize_login_mfa_step(self, user_id)` | No | Will be called once before display the mfa step of login flow. This is not initialization for the MFA module but the mfa step in login flow. - -## Setup Flow - -Before user can use a multi-factor auth module, it has to be enabled or set up. All available modules will be listed in user profile page, user can enable the module he/she wants to use. A setup data entry flow will guide user finish the necessary steps. - -Each MFA module need to implement a setup flow handler extends from `mfa_modules.SetupFlow` (if only one simple setup step need, `SetupFlow` can be used as well). For example for Google Authenticator (TOTP, Time-based One Time Password) module, the flow will need to be: -- Generate a secret and store it on instance of setup flow -- Return `async_show_form` with a QR code in the description (injected as base64 via `description_placeholders`) -- User scans code and enters a code to verify it scanned correctly and clock in synced -- TOTP module saved the secret along with user_id, module is enabled for user - -## Workflow - -![Multi Factor Authentication Workflow](/img/en/auth/mfa_workflow.png) - - - -## Configuration example - -```yaml -# configuration.xml -homeassistant: - auth_providers: - - type: homeassistant - - type: legacy_api_password - auth_mfa_modules: - - type: totp - - type: insecure_example - users: [{'user_id': 'a_32_bytes_length_user_id', 'pin': '123456'}] -``` - -In this example, user will first select from `homeassistant` or `legacy_api_password` auth provider. For `homeassistant` auth provider, user will first input username/password, if that user enabled both `totp` and `insecure_example`, then user need select one auth module, then input Google Authenticator code or input pin code base on the selection. - -> insecure_example is only for demo purpose, please do not use it in production. - -## Validation session - -Not like auth provider, auth module use session to manage the validation. After auth provider validated, mfa module will create a validation session, include an experiation time and user_id from auth provider validate result. Mutli-factor auth module will not only verify the user input, but also verify the session is not expired. The validation session data is stored in your configuration directory. diff --git a/website/versioned_docs/version-0.92.0/creating_integration_manifest.md b/website/versioned_docs/version-0.92.0/creating_integration_manifest.md deleted file mode 100644 index ab57d617..00000000 --- a/website/versioned_docs/version-0.92.0/creating_integration_manifest.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: Integration Manifest -sidebar_label: Manifest -id: version-0.92.0-creating_integration_manifest -original_id: creating_integration_manifest ---- - -Since 0.92.0, every integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, including for custom components. - -```json -{ - "domain": "hue", - "name": "Philips Hue", - "documentation": "https://www.home-assistant.io/components/hue", - "dependencies": ["mqtt"], - "codeowners": ["@balloob"], - "requirements": ["aiohue==1.9.1"] -} -``` - -Or a minimal example that you can copy into your project: - -```json -{ - "domain": "your_domain_name", - "name": "Your Intgration", - "documentation": "https://www.example.com", - "dependencies": [], - "codeowners": [], - "requirements": [] -} -``` - -## Domain - -The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. - -## Name - -The name of the integration. - -## Documentation - -The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/` - -## Dependencies - -Dependencies are other Home Assistant integrations that you want Home Assistant to set up successfully prior to the integration being loaded. This can be necessary in case you want to offer functionality from that other integration, like using webhooks or an MQTT connection. - -## Code Owners - -GitHub usernames or team names of people that are responsible for this integration. You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included. - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you running in a virtual environment. This will make sure that all requirements are present at startup. If steps fail, like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is an array of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v3.2.0: `["pychromecast==3.2.0"]`. - -> Because of how Home Assistant installs requirements on demand, actual Python imports of your requirements should be done inside functions instead of at the root level of your Python files. - -### Custom requirements during development & testing - -During the development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using `pychromecast` as an example: - -```bash -pip install pychromecast==3.2.0 --target ~/.homeassistant/deps -hass --skip-pip -``` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is specified in `requirements`. - -If you need to make changes to a requirement to support your component, it's also possible to install a development version of the requirement using `pip install -e`: - -```bash -git clone https://github.com/balloob/pychromecast.git -pip install -e ./pychromecast -hass --skip-pip -``` diff --git a/website/versioned_docs/version-0.92.0/creating_platform_index.md b/website/versioned_docs/version-0.92.0/creating_platform_index.md deleted file mode 100644 index f235c639..00000000 --- a/website/versioned_docs/version-0.92.0/creating_platform_index.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Integration Platforms -sidebar_label: Platforms -id: version-0.92.0-creating_platform_index -original_id: creating_platform_index ---- - -Home Assistant has various built-in integrations that abstract device types. There are [lights](entity_light.md), [switches](entity_switch.md), [covers](entity_cover.md), [climate devices](entity_climate.md), and [many more](entity_index.md). Your integration can hook into these integrations by creating a platform. You will need a platform for each integration that you are integrating with. - -To create a platform, you will need to create a file with the domain name of the integration that you are building a platform for. So if you are building a light, you will add a new file `light.py` to your integration folder. - -We have created two example integrations that should give you a look at how this works: - - - [Example sensor platform](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_sensor/): hello world of platforms. - - [Example light platform](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_light/): showing best practices. - -### Interfacing with devices - -One Home Assistant rule is that the integration should never interface directly with devices. Instead, it should interact with a third-party Python 3 library. This way, Home Assistant can share code with the Python community and keep the project maintainable. - -Once you have your Python library ready and published to PyPI, add it to the [manifest](creating_integration_manifest.md). It will now be time to implement the Entity base class that is provided by the integration that you are creating a platform for. - -Find your integration at the [entity index](entity_index.md) to see what methods and properties are available to implement. diff --git a/website/versioned_docs/version-0.92.0/development_submitting.md b/website/versioned_docs/version-0.92.0/development_submitting.md deleted file mode 100644 index 8c8144ac..00000000 --- a/website/versioned_docs/version-0.92.0/development_submitting.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -title: Submit your work -id: version-0.92.0-development_submitting -original_id: development_submitting ---- - -> Always base your Pull Requests of of the current **`dev`** branch, not `master`. - -Submit your improvements, fixes, and new features to Home Assistant one at a time, using GitHub [Pull Requests](https://help.github.com/articles/using-pull-requests). Here are the steps: - - 1. From your fork's dev branch, create a new branch to hold your changes: - - `git checkout -b some-feature` - - 2. Make your changes, create a [new platform](creating_platform_index.md), develop a [new component](creating_component_index.md), or fix [issues](https://github.com/home-assistant/home-assistant/issues). - - 3. [Test your changes](development_testing.md) and check for style violations. - - 4. If everything looks good according to these [musts](development_checklist.md), commit your changes: - - `git add .` - - `git commit -m "Add some-feature"` - - * Write a meaningful commit message and not only `Update` or `Fix`. - * Use a capital letter to start with your commit message. - * Don't prefix your commit message with `[bla.bla]` or `platform:`. - * Consider adding tests to ensure that your code works. - - 5. Push your committed changes back to your fork on GitHub: - - `git push origin HEAD` - - 6. Follow [these steps](https://help.github.com/articles/creating-a-pull-request/) to create your pull request. - - * On GitHub, navigate to the main page of the Home Assistant repository. - * In the "Branch" menu, choose the branch that contains your commits (from your fork). - * To the right of the Branch menu, click **New pull request**. - * Use the base branch dropdown menu to select the branch you'd like to merge your changes into, then use the compare branch drop-down menu to choose the topic branch you made your changes in. Make sure the Home Assistant branch matches with your forked branch (`dev`) else you will propose ALL commits between branches. - * Type a title and complete the provided description for your pull request. - * Click **Create pull request**. - - 7. Check for comments and suggestions on your pull request and keep an eye on the [CI output](https://travis-ci.org/home-assistant/home-assistant/). - diff --git a/website/versioned_docs/version-0.92.0/entity_climate.md b/website/versioned_docs/version-0.92.0/entity_climate.md deleted file mode 100644 index 2b65d6c2..00000000 --- a/website/versioned_docs/version-0.92.0/entity_climate.md +++ /dev/null @@ -1,233 +0,0 @@ ---- -title: Climate Entity -sidebar_label: Climate -id: version-0.92.0-entity_climate -original_id: entity_climate ---- - -> A climate entity is a device that controls temperature, humidity, or fans, such as A/C systems and humidifiers. Derive entity platforms from [`homeassistant.components.climate.ClimateDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/climate/__init__.py) - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| current_fan_mode | string | None | Returns the current fan mode. -| current_hold_mode | string | None | The current hold mode, e.g., home, away, temp. -| current_humidity | float | None | The current humidity. -| current_operation | string | None | The current operation (e.g. heat, cool, idle). Used to determine `state`. -| current_swing_mode | string | None | Returns the fan setting. -| current_temperature | float | None | The current temperature. -| fan_list | list | None | Returns the list of available fan modes. -| is_aux_heat_on | bool | None | Returns True if an auxiliary heater is on. -| is_away_mode_on | bool | None | Return true if away mode is on. -| is_on | bool | None | Returns True if device is on. Used to determine `state`. -| max_humidity | int | `DEFAULT_MAX_HUMIDITY` (value == 99) | Returns the maximum humidity. -| max_temp | int | `DEFAULT_MAX_TEMP` (value == 35) | Returns the maximum temperature. -| min_humidity | int | `DEFAULT_MIN_HUMIDITY` (value == 30) | Returns the minimum humidity. -| min_temp | int | `DEFAULT_MIN_TEMP` (value == 7) | Returns the minimum temperature. -| operation_list | list | None | List of available operation modes. -| precision | float | PRECISION_WHOLE | The precision of the temperature in the system: tenths for TEMP_CELSIUS, whole number otherwise. -| state | string | None | Returns the current state. -| state_attributes | dictionary | N/A | The optional state attributes: current temperature, minimum temperature, maximum temperature, and target temperature. -| supported_features | list | `NotImplementedError()` | Returns list of supported features. -| swing_list | list | None | Returns the list of available swing modes. -| target_humidity | float | None | The target humidity. -| target_temperature | float | None | The temperature currently set to be reached. -| target_temperature_high | float | None | The upper bound target temperature -| target_temperature_low | float | None | The lower bound target temperature -| target_temperature_step | float | None | The supported step of target temperature -| temperature_unit | string | `NotImplementedError` | The unit of temperature measurement for the system (e.g. Celsius). - -### States - -| Name | Description -| ---- | ----------- -| STATE_HEAT | The device is set to heat. -| STATE_COOL | The device is set to cool. -| STATE_IDLE | The device is idle. -| STATE_AUTO | The device is set to auto. -| STATE_MANUAL | The device is set to manual. -| STATE_DRY | The device is set to dry. -| STATE_FAN_ONLY | The device is set to fan-only. -| STATE_ECO | The device is set to eco-mode. - -### Supported features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Name | Description -| ---- | ----------- -| SUPPORT_TARGET_TEMPERATURE | The device supports a target temperature. -| SUPPORT_TARGET_TEMPERATURE_HIGH | The device supports an upper bound target temperature. -| SUPPORT_TARGET_TEMPERATURE_LOW | The device supports a lower bound target temperature. -| SUPPORT_TARGET_HUMIDITY | The device supports a target humidity. -| SUPPORT_TARGET_HUMIDITY_HIGH | The device supports an upper bound target humidity. -| SUPPORT_TARGET_HUMIDITY_LOW | The device supports a lower bound target humidity. -| SUPPORT_FAN_MODE | The device supports fan modes. -| SUPPORT_OPERATION_MODE | The device supports operation modes. -| SUPPORT_HOLD_MODE | The device supports hold modes. -| SUPPORT_SWING_MODE | The device supports swing modes. -| SUPPORT_AWAY_MODE | The device supports away mode. -| SUPPORT_AUX_HEAT | The device supports auxiliary heaters. -| SUPPORT_ON_OFF | The device supports on/off states. - - -## Methods - -### Set fan mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_fan_mode(self, fan_mode): - """Set new target fan mode.""" - - async def async_set_fan_mode(self, fan_mode): - """Set new target fan mode.""" -``` - -### Set hold mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_hold_mode(self, hold_mode): - """Set new target hold mode.""" - - async def async_set_hold_mode(self, hold_mode): - """Set new target hold mode.""" -``` - -### Set humidity - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_humidity(self, humidity): - """Set new target humidity.""" - - async def async_set_humidity(self, humidity): - """Set new target humidity.""" -``` - -### Set operation mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_operation_mode(self, operation_mode): - """Set new target operation mode.""" - - async def async_set_operation_mode(self, operation_mode): - """Set new target operation mode.""" -``` - -### Set swing mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_swing_mode(self, swing_mode): - """Set new target swing operation.""" - - async def async_set_swing_mode(self, swing_mode): - """Set new target swing operation.""" -``` - -### Set temperature - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_temperature(self, **kwargs): - """Set new target temperature.""" - - async def async_set_temperature(self, **kwargs): - """Set new target temperature.""" -``` - -### Turn auxiliary heater on - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_aux_heat_on(self): - """Turn auxiliary heater on.""" - - async def async_turn_aux_heat_on(self): - """Turn auxiliary heater on.""" -``` - -### Turn auxiliary heater off - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_aux_heat_off(self): - """Turn auxiliary heater off.""" - - async def async_turn_aux_heat_off(self): - """Turn auxiliary heater off.""" -``` - -### Turn away mode on - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_away_mode_on(self): - """Turn away mode on.""" - - async def async_turn_away_mode_on(self): - """Turn away mode on.""" -``` - -### Turn away mode off - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_away_mode_off(self): - """Turn away mode off.""" - - async def async_turn_away_mode_off(self): - """Turn away mode off.""" -``` - -### Turn the device on - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_on(self): - """Turn device on.""" - - async def async_turn_on(self): - """Turn device on.""" -``` - -### Turn the device off - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_off(self): - """Turn device off.""" - - async def async_turn_off(self): - """Turn device off.""" -``` diff --git a/website/versioned_docs/version-0.92.0/entity_fan.md b/website/versioned_docs/version-0.92.0/entity_fan.md deleted file mode 100644 index b8e01284..00000000 --- a/website/versioned_docs/version-0.92.0/entity_fan.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Fan Entity -sidebar_label: Fan -id: version-0.92.0-entity_fan -original_id: entity_fan ---- - -A fan entity is a device that controls the different vetors of your fan susch as speed, direction and oscillation. Derive enitity platforms from ['homeassistant.components.fan.FanDevice'](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/fan/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| current_direction | str | None | Return the current direction of the fan | -|is_on| boolean | None |Return true if the entity is on | -| speed | str | None | Return the current speed | -| speed_list | list | None| Get the list of available speeds | -| state_attributes | dict | None | Return optional state attributes | -| supported_features | int | None | Flag supported features | - - -## Supported Features - -| Constant | Description | -|----------|--------------------------------------| -| 'SUPPORT_DIRECTION' | The fan supports changing the direction of it. -| 'SUPPORT_SET_SPEED' | The fan supports setting the speed. -| 'SUPPORT_OSCILLATE' | The fan supports oscillation. - - - -## Methods - -### Set direction - -Only implement this method if the flag `SUPPORT_DIRECTION` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def set_direction(self, direction: str) -> None: - """Set the direction of the fan.""" - - async def async_set_direction(self, direction: str): - """Set the direction of the fan.""" -``` - -### Set speed - -Only implement this method if the flag `SUPPORT_SET_SPEED` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def set_speed(self, speed: str) -> None: - """Set the speed of the fan.""" - - async def async_set_speed(self, speed: str): - """Set the speed of the fan.""" -``` - -### Turn on - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def turn_on(self, speed: str = None, **kwargs) -> None: - """Turn on the fan.""" - - async def async_turn_on(self, speed: str = None, **kwargs): - """Turn on the fan.""" -``` - -### Oscillate - -Only implement this method if the flag `SUPPORT_OSCILLATE` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def oscillate(self, oscillating: bool) -> None: - """Oscillate the fan.""" - - def async_oscillate(self, oscillating: bool): - """Oscillate the fan.""" -``` - - - - - - diff --git a/website/versioned_docs/version-0.92.0/entity_media_player.md b/website/versioned_docs/version-0.92.0/entity_media_player.md deleted file mode 100644 index 886e43be..00000000 --- a/website/versioned_docs/version-0.92.0/entity_media_player.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Media Player Entity -sidebar_label: Media Player -id: version-0.92.0-entity_media_player -original_id: entity_media_player ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| sound_mode | string | None | The current sound mode of the media player -| sound_mode_list | list | None | Dynamic list of available sound modes (set by platform, empty means sound mode not supported) -| source | string | None | The currently selected input source for the media player. -| source_list | list | None | The list of possible input sources for the media player. (This list should contain human readable names, suitible for frontend display) -| media_image_url | string | None | URL that represents the current image. -| media_image_remotely_accessible | boolean | False | Return `True` if property `media_image_url` is accessible outside of the home network. - -## Methods -### Select sound mode -Optional. Switch the sound mode of the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - def async_select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - -### Select source -Optional. Switch the selected input source for the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_source(self, source): - """Select input source.""" - - def async_select_source(self, source): - """Select input source.""" - -### Mediatype -Required. Returns one of the defined constants from the below list that matches the mediatype - -| CONST | -|-------| -|MEDIA_TYPE_MUSIC| -|MEDIA_TYPE_TVSHOW| -|MEDIA_TYPE_MOVIE| -|MEDIA_TYPE_VIDEO| -|MEDIA_TYPE_EPISODE| -|MEDIA_TYPE_CHANNEL| -|MEDIA_TYPE_PLAYLIST| -|MEDIA_TYPE_IMAGE| -|MEDIA_TYPE_URL| -|MEDIA_TYPE_GAME| - - class MyMediaPlayer(MediaPlayerDevice): - # Implement the following method. - - def media_content_type(self): - """Content type of current playing media.""" - diff --git a/website/versioned_docs/version-0.92.0/entity_registry_index.md b/website/versioned_docs/version-0.92.0/entity_registry_index.md deleted file mode 100644 index 0a868379..00000000 --- a/website/versioned_docs/version-0.92.0/entity_registry_index.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Entity Registry -sidebar_label: Introduction -id: version-0.92.0-entity_registry_index -original_id: entity_registry_index ---- - -The entity registry is a registry where Home Assistant keeps track of entities. Any entity that is added to Home Assistant and has a unique ID will be registered in the registry. - -Being registered has the advantage that the same entity will always get the same entity ID. It will also prevent other entities from using that entity ID. - -A user is also able to override the name of an entity in the entity registry. When set, the name of the entity registry is used in favor of the name the device might give itself. - -## Unique ID requirements - -An entity is looked up in the registry based on a combination of the plaform type (e.g., `light`), and the integraion name (domain) (ie hue) and the unique ID of the entity. It is therefore very important that the unique ID is unique! It is also important that it is not possible for the user to change the unique ID, because that means it will lose all its settings related to it. - -Good sources for a unique ID: - - - Serial number of a device - - MAC address of a device - - latitude/longitude - -If a device has a single serial but provides multiple entities, combine the serial with unique identifiers for the entities. For example, if a device measures both temperature and humidity, you can uniquely identify the entities using `{serial}-{sensor_type}`. diff --git a/website/versioned_docs/version-0.92.0/external_api_websocket.md b/website/versioned_docs/version-0.92.0/external_api_websocket.md deleted file mode 100644 index 1cd2189a..00000000 --- a/website/versioned_docs/version-0.92.0/external_api_websocket.md +++ /dev/null @@ -1,436 +0,0 @@ ---- -title: WebSocket API -id: version-0.92.0-external_api_websocket -original_id: external_api_websocket ---- - -Home Assistant contains a WebSocket API. This API can be used to stream information from a Home Assistant instance to any client that implements WebSockets. Implementations in different languages: - -- [JavaScript](https://github.com/home-assistant/home-assistant-js-websocket) - powers the frontend -- [Python](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket-client.py) - CLI client using [`asyncws`](https://async-websockets.readthedocs.io/en/latest/) -- [JavaScript/HTML](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket.html) - WebSocket connection in your browser - -Connect your websocket implementation to `ws://localhost:8123/api/websocket`. You will need a valid access token. - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`websocket_api` component](https://www.home-assistant.io/components/websocket_api/) to your `configuration.yaml` file to use the WebSocket API. - -## Server states - -1. Client connects. -1. Authentication phase starts. - - Server sends `auth_required` message. - - Client sends `auth` message. - - If `auth` message correct: go to 3. - - Server sends `auth_invalid`. Go to 6. -1. Send `auth_ok` message -1. Authentication phase ends. -1. Command phase starts. - 1. Client can send commands. - 1. Server can send results of previous commands. -1. Client or server disconnects session. - -During the command phase, the client attaches a unique identifier to each message. The server will add this identifier to each message so that the client can link each message to its origin. - -## Message format - -Each API message is a JSON serialized object containing a `type` key. After the authentication phase messages also must contain an `id`, an integer that contains the number of interactions. - -Example of an auth message: - -```json -{ - "type": "auth", - "access_token": "ABCDEFGHIJKLMNOPQ" -} -``` - -```json -{ - "id": 5, - "type":"event", - "event":{ - "data":{}, - "event_type":"test_event", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -## Authentication phase - -When a client connects to the server, the server will test if the client is authenticated. Authentication will not be necessary if no api_password is set or if the user fulfills one of the other criteria for authentication (trusted network, password in url/header). - -If no authentication is needed, the authentication phase will complete and the server will send an `auth_ok` message. - -```json -{ - "type": "auth_ok" -} -``` - -If authentication is necessary, the server sends out `auth_required`. - -```json -{ - "type": "auth_required" -} -``` - -This means that the next message from the client should be an auth message. You can authorize with an access token. - -```json -{ - "type": "auth", - "access_token": "ABCDEFGH" -} -``` - -For now, we also support authentication with an API password (legacy auth). - -```json -{ - "type": "auth", - "api_password": "supersecret" -} -``` - -If the client supplies valid authentication, the authentication phase will complete by the server sending the `auth_ok` message: - -```json -{ - "type": "auth_ok" -} -``` - -If the data is incorrect, the server will reply with `auth_invalid` message and disconnect the session. - -```json -{ - "type": "auth_invalid", - "message": "Invalid password" -} -``` - -## Command phase - -During this phase the client can give commands to the server. The server will respond to each command with a `result` message indicating when the command is done and if it was successful. - -```json -{ - "id": 6, - "type": "result", - "success": true, - // Can contain extra result info - "result": null -} -``` - -## Subscribe to events - -The command `subscribe_events` will subscribe your client to the event bus. You can either listen to all events or to a specific event type. If you want to listen to multiple event types, you will have to send multiple `subscribe_events` commands. - -```json -{ - "id": 18, - "type": "subscribe_events", - // Optional - "event_type": "state_changed" -} -``` - -The server will respond with a result message to indicate that the subscription is active. - -```json -{ - "id": 18, - "type": "result", - "success": true, - "result": null -} -``` - -For each event that matches, the server will send a message of type `event`. The `id` in the message will point at the original `id` of the `listen_event` command. - -```json -{ - "id": 18, - "type":"event", - "event":{ - "data":{ - "entity_id":"light.bed_light", - "new_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:24.265390+00:00", - "state":"on", - "attributes":{ - "rgb_color":[ - 254, - 208, - 0 - ], - "color_temp":380, - "supported_features":147, - "xy_color":[ - 0.5, - 0.5 - ], - "brightness":180, - "white_value":200, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:24.265390+00:00" - }, - "old_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:10.466994+00:00", - "state":"off", - "attributes":{ - "supported_features":147, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:10.466994+00:00" - } - }, - "event_type":"state_changed", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -### Unsubscribing from events - -You can unsubscribe from previously created subscription events. Pass the id of the original subscription command as value to the subscription field. - -```json -{ - "id": 19, - "type": "unsubscribe_events", - "subscription": 18 -} -``` - -The server will respond with a result message to indicate that unsubscribing was successful. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": null -} -``` - -## Calling a service - -This will call a service in Home Assistant. Right now there is no return value. The client can listen to `state_changed` events if it is interested in changed entities as a result of a service call. - -```json -{ - "id": 24, - "type": "call_service", - "domain": "light", - "service": "turn_on", - // Optional - "service_data": { - "entity_id": "light.kitchen" - } -} -``` - -The server will indicate with a message indicating that the service is done executing. - -```json -{ - "id": 24, - "type": "result", - "success": true, - "result": null -} -``` - -## Fetching states - -This will get a dump of all the current states in Home Assistant. - -```json -{ - "id": 19, - "type": "get_states" -} -``` - -The server will respond with a result message containing the states. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -## Fetching config - -This will get a dump of the current config in Home Assistant. - -```json -{ - "id": 19, - "type": "get_config" -} -``` - -The server will respond with a result message containing the config. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -## Fetching services - -This will get a dump of the current services in Home Assistant. - -```json -{ - "id": 19, - "type": "get_services" -} -``` - -The server will respond with a result message containing the services. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -## Fetching panels - -This will get a dump of the current registered panels in Home Assistant. - -```json -{ - "id": 19, - "type": "get_panels" -} -``` - -The server will respond with a result message containing the current registered panels. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -## Fetching camera thumbnails - -_Introduced in Home Assistant 0.69._ - -Return a b64 encoded thumbnail of a camera entity. - -```json -{ - "id": 19, - "type": "camera_thumbnail" -} -``` - -The server will respond with a result message containing the thumbnail. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Fetching media player thumbnails - -_Introduced in Home Assistant 0.69._ - -Fetch a base64 encoded thumbnail picture for a media player. - -```json -{ - "id": 19, - "type": "media_player_thumbnail", - "entity_id": "media_player.living_room" -} -``` - -The server will respond with the image encoded via base64. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Pings and Pongs - -The API supports receiving a ping from the client and returning a pong. This serves as a heartbeat to ensure the connection is still alive: - -```json -{ - "id": 19, - "type": "ping" -} -``` - -The server must send a pong back as quickly as possible, if the connection is still active: - -```json -{ - "id": 19, - "type": "pong" -} -``` - -## Error handling - -If an error occurs, the `success` key in the `result` message will be set to `false`. It will contain an `error` key containing an object with two keys: `code` and `message`. - -| Code | Description | -| ----- | ------------ | -| 1 | A non-increasing identifier has been supplied. -| 2 | Received message is not in expected format (voluptuous validation error). -| 3 | Requested item cannot be found - -```json -{ - "id": 12, - "type":"result", - "success": false, - "error": { - "code": 2, - "message": "Message incorrectly formatted: expected str for dictionary value @ data['event_type']. Got 100" - } -} -``` diff --git a/website/versioned_docs/version-0.92.0/hassio_addon_communication.md b/website/versioned_docs/version-0.92.0/hassio_addon_communication.md deleted file mode 100644 index cbb71f66..00000000 --- a/website/versioned_docs/version-0.92.0/hassio_addon_communication.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Add-On Communication -id: version-0.92.0-hassio_addon_communication -original_id: hassio_addon_communication ---- - -There are different ways for communication between add-ons inside Hass.io. - -## Network - -We use an internal network that allows to communicate with every add-on, even to/from Home Assistant, by using its name or alias. Only the add-ons which run on the host network are a bit limited. These can talk with all internal add-ons by their name but all other add-on can't address these add-on by name - using an alias works for both! - -Name/alias are used for communication inside Hass.io. -The name is generated using the following format: `{REPO}_{SLUG}`, e.g., `local_xy` or `3283fh_myaddon`. In this example, `{SLUG}` is defined in an add-ons `config.json`. You can use this name also as DNS name but you need replace the `_` with `-` to have a valid hostname. If an add-on is installed locally, `{REPO}` will be `local`. If the add-on is installed from a Github repository, `{REPO}` is a hashed identifier generated from the GitHub repository's URL (ex: https://github.com/xy/my_hassio_addons). See [here](https://github.com/home-assistant/hassio/blob/587047f9d648b8491dc8eef17dc6777f81938bfd/hassio/addons/utils.py#L17) to understand how this identifier is generated. Note that this identifier is required in certain service calls that use the [Hass.io add-on API][hassio-addon-api]. You can view the repository identifiers for all currently installed add-ons via a GET request to the hassio API `addons` endpoint. - -Use `hassio` for communication with the internal API. - -## Home Assistant - -An add-on can talk to the [Home Assistant API][hass-api] using the internal proxy. That makes it very easy to communicate with the API without knowing the password, port or any other information of the Home Assistant instance. Use this URL: `http://hassio/homeassistant/api` and internal communication is redirected to the right place. The next stept is to add `homeassistant_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN` and use this as Home-Assistant password. - -There is also a proxy for the [Home Assistant Websocket API][hass-websocket]. It works like the API proxy above and requires `HASSIO_TOKEN` as password. Use this URL: `http://hassio/homeassistant/websocket`. - -It is also possible to talk direct to the Home Assistant instance which is named `homeassistant` over the internal network. But you need to know the configuration that is used by the running instance. - -We have severals services for Hass.io inside Home Assistant to run tasks. To send data over STDIN to an add-on use the `hassio.addon_stdin` service. - -## Hass.io API - -To enables calls to the [Hass.io API][hassio-api], add `hassio_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN`. Now you can use the API over the URL: `http://hassio/`. Use the `HASSIO_TOKEN` with header `X-HASSIO-KEY`. It could be that you need also change the Hass.io API role like `hassio_role: default`. - -Add-ons can call some API commands without need set `hassio_api: true`: -- `/homeassistant/api` -- `/homeassistant/api/stream` -- `/homeassistant/websocket` -- `/addons/self/*` -- `/services*` -- `/discovery*` -- `/info` - -***Note:*** Fore Home Assistant API access requirements look above. - -[hass-api]: https://www.home-assistant.io/developers/rest_api/ -[hass-websocket]: https://www.home-assistant.io/developers/websocket_api/ -[hassio-api]: https://github.com/home-assistant/hassio/blob/master/API.md -[hassio-addon-api]: https://github.com/home-assistant/hassio/blob/dev/API.md#restful-for-api-addons diff --git a/website/versioned_docs/version-0.92.0/hassio_addon_config.md b/website/versioned_docs/version-0.92.0/hassio_addon_config.md deleted file mode 100644 index 4502854a..00000000 --- a/website/versioned_docs/version-0.92.0/hassio_addon_config.md +++ /dev/null @@ -1,228 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.92.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - apparmor.txt - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -All our Images have also [bashio][bashio] installed. It contains a set of commonly used operations and can be used to be included in add-ons to reduce code duplication across add-ons and therefore making it easier to develop and maintain add-ons. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use bashio or `jq` inside your shell script to parse this data. - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -[bashio]: https://github.com/hassio-addons/bashio - -## Add-on Docker file - -All add-ons are based on latest Alpine Linux. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | yes | List of supported arch: `armhf`, `armv7`, `aarch64`, `amd64`, `i386`. -| machine | list | no | Default it support any machine type. You can select that this add-on run only on specific machines. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| homeassistant | string | no | Pin a minimun required Home Assistant version for such Add-on. Value is a version string like `0.91.2`. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| kernel_modules | bool | no | Map host kernel modules and config into add-on (readonly). -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| auth_api | bool | no | Allow access to Home Assistent user backend. -| ingress | bool | no | Enable the ingress feature for the Add-on -| ingress_port | integer | no | Default `8099`. For Add-ons they run on host network, you can use `0` and read the port later on API. -| ingress_entry | string | no | Modify the URL entry point from `/`. -| panel_icon | string | no | Default: mdi:puzzle. MDI icon for the menu panel integration. -| panel_title | string | no | Default add-on name, but can Modify with this options. -| panel_admin | bool | no | Default True. Make menu entry only available with admin privileged. - - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. - -We provide a set of [Base-Images][hassio-base] which should cover a lot of needs. If you don't want use the Alpine based version or need a specific Image tag, feel free to pin this requirements for you build with `build_from` option. - -[hassio-base]: https://github.com/home-assistant/hassio-base diff --git a/website/versioned_docs/version-0.92.0/hassio_addon_index.md b/website/versioned_docs/version-0.92.0/hassio_addon_index.md deleted file mode 100644 index 51183d96..00000000 --- a/website/versioned_docs/version-0.92.0/hassio_addon_index.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Developing an add-on -sidebar_label: Introduction -id: version-0.92.0-hassio_addon_index -original_id: hassio_addon_index ---- - -Add-ons for Hass.io allow the user to extend the functionality around Home Assistant. This can be running an application that Home Assistant can integrate with (like an MQTT broker) or to share the configuration via Samba for easy editing from other computers. Add-ons can be configured via the Hass.io panel in Home Assistant. - -Under the hood, add-ons are Docker images published in [Docker Hub](https://hub.docker.com/). Developers can create [GitHub](https://github.com) repositories that contain multiple references to add-ons for easy sharing with the community. - -1. [Tutorial: Making your first add-on](hassio_addon_tutorial.md) -1. [Configuration](hassio_addon_config.md) -1. [Communication](hassio_addon_communication.md) -1. [Local Testing](hassio_addon_testing.md) -1. [Publishing](hassio_addon_publishing.md) -1. [Presentation](hassio_addon_presentation.md) -1. [Repositories](hassio_addon_repository.md) -1. [Security](hassio_addon_security.md) - - -Usefully links: - -* [Hass.io Supervisor](https://github.com/home-assistant/hassio) -* [Hass.io Core Add-ons](https://github.com/home-assistant/hassio-addons) -* [Hass.io Build environment](https://github.com/home-assistant/hassio-build) -* [Hass.io base images](https://github.com/home-assistant/hassio-base) -* [Hass.io Builder](https://github.com/home-assistant/hassio-builder) -* [Hass.io community Add-ons](https://github.com/hassio-addons) -* [HassOS embedded Linux](https://github.com/home-assistant/hassos) -* [Home Assistant Dockerfile](https://github.com/home-assistant/hassio-homeassistant) diff --git a/website/versioned_docs/version-0.92.0/hassio_addon_presentation.md b/website/versioned_docs/version-0.92.0/hassio_addon_presentation.md deleted file mode 100644 index d85c73c6..00000000 --- a/website/versioned_docs/version-0.92.0/hassio_addon_presentation.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Presenting your add-on -id: version-0.92.0-hassio_addon_presentation -original_id: hassio_addon_presentation ---- - -If you decide to share your add-on to the public, paying attention to details is recommended. Of course, your add-on should have a proper name and description, but Hass.io also gives you some other tools to present your add-on even nicer. - -## Adding documentation - -Good documentation helps the consumer of your add-on to understand its usage, explains configuration options, points users in the right direction in the case they have questions or issues, and contains the license under which the add-on was published. - -This file containing the documentation is usually referred to as the "README", which is generally published as the `README.md` file. - -Take a look at other projects for inspiration. For example, see the `README.md` of the [Community Hass.io Add-ons: Homebridge](https://github.com/hassio-addons/addon-homebridge/blob/master/README.md) add-on. - -In future versions of Hass.io, the `README.md` file will be displayed in the Home Assistant frontend. - -## Add-on icon & logo - -A picture is worth a thousand words. Therefore, your add-on can be improved by adding a proper image icon and logo. Those images are used when showing your add-on in the Home Assistant Hass.io panel and which will significantly improve the visual representation of your add-on. - -Requirements for the logo of your add-on: - -- The logo must be in the Portable Network Graphics format (`.png`). -- The filename must be `logo.png`. -- It is recommended to keep the logo size around 250x100px. You may choose to use a different size or aspect ratio as you seem fit for your add-on. - -Requirements for the icon of your add-on: - -- The icon must be in the Portable Network Graphics format (`.png`). -- The filename must be `icon.png`. -- The aspect ratio of the icon must be 1x1 (square). -- It is recommended to use an icon size of 128x128px. - -## Keeping a changelog - -It is likely you are going to release newer versions of your add-on in the future. In case that happens, the users of your add-on would see an upgrade notice and probably want to know what changes were made in the latest version. - -A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of your add-on and is generally published as the `CHANGELOG.md` file. - -If you are in need of a guide on keeping a changelog, we would recommend checking the [keep a changelog](http://keepachangelog.com) website. They have developed a standard that is used by many opensource projects around the world. - -In future versions of Hass.io, the `CHANGELOG.md` file will be displayed in the Home Assistant frontend. - -## AppArmor - -You can use own security profile for you Add-on with AppArmor. Default it is enabled and use the Docker default profile. Put `apparmor.txt` file into your Add-on folder and it will load this file as primary profile. Use the config options to set the name of that profile. - -## Ingress - -Ingress allow users to access the add-on web interface via the Home Assistant UI. Authentication is handled by Home Assistant, so neither the user nor the add-on developer will need to care about the security or port forwarding. Users love this feature, however it is not every time simple to implement for the add-on developer. - -To add Ingress support, follow the following steps: -- The add-on will need to provide the web interface on port `8099`. Make sure that the add-on accepts only connections from `172.30.32.2` on that port and that the connections are treated as authenticated. -- Update add-on configuration and set `ingress: true`. Here it is also possible to configure the Ingress port (default 8099). -- If you need to configure the application inside your add-on with the right path and port, query the add-on info API endpoint. -- If the application doesn't support relative paths or you can't set a base url, you can use nginx filter to replace the URL with correct path. - -Ingress API gateway supports the following: - - * HTTP/1.x - * Streaming content - * Websockets diff --git a/website/versioned_docs/version-0.92.0/hassio_addon_publishing.md b/website/versioned_docs/version-0.92.0/hassio_addon_publishing.md deleted file mode 100644 index c81ceff9..00000000 --- a/website/versioned_docs/version-0.92.0/hassio_addon_publishing.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Publishing your add-on -id: version-0.92.0-hassio_addon_publishing -original_id: hassio_addon_publishing ---- - -There are two different ways of publishing add-ons. One is to publish pre-build containers to Docker Hub and the other option is to have users build the containers locally on their Hass.io instance. - -#### Pre-build containers - -With pre-build containers, the developer is responsible for building the images for each architecture on their machine and push the results out to Docker Hub. This has a lot of advantages for the user. As a user it will only have to download the final container and be up and running once the download finishes. This makes the installation process fast and almost no chance of failure. This is the preferred method. - -We have automated the process of building and publishing add-ons. See below for the instructions. - -#### Locally build containers - -Starting Hass.io 0.26, it is possible to distribute add-ons that will be built on the users machine. The advantage is that as a developer it is easy to test an idea and see if people are interested in your add-ons. This method includes installing and potentially compiling code. This means that installing such an add-on is slow and adds more wear and tear to users SD card/hard drive than the above mentioned pre-build solution. It also has a higher chance of failure if one of the dependencies of the container has changed or is no longer available. - -Use this option when you are playing with add-ons and seeing if someone is interested in your work. Once you're an established repository, please migrate to pushing builds to Docker Hub as it greatly improves the user experience. In the future we will mark locally built add-ons in the add-on store to warn users. - -## Build scripts to publish add-ons to Docker Hub - -All add-ons are simple docker containers. Inside your add-on `config.json` you specify the Docker image that will be installed for your add-on: - -```json -{ - ... - "image": "myhub/image-{arch}-addon-name", - ... -} -``` - -You can use `{arch}` inside the image name to support multiple architectures with one (1) configuration file. It will be replaced with the architecture of the user when we load the image. If you use `Buildargs` you can use the `build.json` to overwrite our default args. - -Hass.io assumes that the `master` branch of your add-on repository matches the latest tag on Docker Hub. When you're building a new version, it's suggested that you use another branch, ie `build` or do it with a PR on GitHub. After you push the add-on to [Docker Hub](https://hub.docker.com/), you can merge this branch to master. - -## Custom Add-ons - -You need a Docker Hub account to make your own add-ons. You can build your Docker images with the Docker `build` command or use our script that make it simple. Pull our [Builder Docker engine][builder] and run one of the following commands. - -For a git repository: - -```bash -$ docker run --rm --privileged -v \ - ~/.docker:/root/.docker homeassistant/amd64-builder \ - --all -t addon-folder -r https://github.com/xy/addons \ - -b branchname -``` - -For a local repository: - -```bash -$ docker run --rm --privileged -v \ - ~/.docker:/root/.docker -v /my_addon:/data homeassistant/amd64-builder \ - --all -t /data -``` - -> If you are developing on macOS and using Docker for Mac, you may encounter an error message similar to the following: error creating aufs mount to /var/lib/docker/aufs/mnt/-init: invalid argument. A proposed workaround is to add the following to the Advanced Daemon JSON configuration via Docker > Preferences > Daemon > Advanced: "storage-driver" : "aufs" or map the docker socket into container. - -[builder]: https://github.com/home-assistant/hassio-builder diff --git a/website/versioned_docs/version-0.92.0/hassio_addon_security.md b/website/versioned_docs/version-0.92.0/hassio_addon_security.md deleted file mode 100644 index fdff4ba5..00000000 --- a/website/versioned_docs/version-0.92.0/hassio_addon_security.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Add-on security -id: version-0.92.0-hassio_addon_security -original_id: hassio_addon_security ---- - -Hass.io rates every add-on based on the wanted rights. An add-on with a rating of 6 is very secure. If an add-on has a rating of 1, you shouldn't run this add-on unless you are 100% sure that you can trust the source. - -## API Role - -For access to Hass.io API you need define a role or you run in default mode. This is only required for Hass.io API not Home Assistant proxy. Any of the role have also the default API calls inheret for that are no settings are required. - -### Available Roles - -| Role | Description | -|------|-------------| -| default | Have access to all `info` calls | -| homeassistant | Can access to all Home Assistant API endpoints | -| backup | Can access to all snapshot API endpoints | -| manager | Is for Add-ons they run CLIs and need extended rights | -| admin | Have access to every API call. That is the only one they can disable/enable the Add-on protection mode | - -## Protection - -Default, all add-ons run in protection enabled mode. This mode prevents the add-on from getting any rights on the system. If an add-on requires more rights, you can disable this protection via the API add-on options for that add-on. But be carful, an add-on with disabled protection can destroy your system! - -## Making a secure add-on - -As a developer, follow the following best practices to make your add-on secure: - -- Don't run on host network -- Create an AppArmor profile -- Map folders read only if you don't need write access -- If you need any API access, make sure you that you not grant to highest permission if you don't need it - -## Use Home Assistant User backend - -Instead to allow users to set new login credential in plain text config, use the Home Assistant [Auth backend][hassio-api-auth]. You can enable the access to API with `auth_api: true`. Now you are able to send the login credential to auth backend and validate it again Home Assistant. - -We have some sample and helper around that system collected in a [GitHub repository][hassio-auth]. Feel free to copy past it or provide your usefully scripts. - -[hassio-auth]: https://github.com/home-assistant/hassio-auth -[hassio-api-auth]: https://github.com/home-assistant/hassio/blob/dev/API.md#auth--sso-api diff --git a/website/versioned_docs/version-0.92.0/hassio_addon_testing.md b/website/versioned_docs/version-0.92.0/hassio_addon_testing.md deleted file mode 100644 index 369e5be6..00000000 --- a/website/versioned_docs/version-0.92.0/hassio_addon_testing.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Local add-on testing -id: version-0.92.0-hassio_addon_testing -original_id: hassio_addon_testing ---- - -The fastest way to develop add-ons is by adding them to your local add-on repository. To access your local add-on repository, install either the [Samba add-on] or [SSH add-on]. - -Right now add-ons will work with images that are stored on Docker Hub (using `image` from add-on config). Without `image` inside local add-ons repository it to be built on the device. - -The [Community Add-on][hassio-vagrant] repository create a vagrant based development system. This Vagrant virtual machine allows you to test and play with Hass.io and Home Assistant, and is a great environment for add-on developers - -[Samba add-on]: https://www.home-assistant.io/addons/samba/ -[SSH add-on]: https://www.home-assistant.io/addons/ssh/ -[hassio-vagrant]: https://github.com/hassio-addons/hassio-vagrant - -## Local build - -You can build and try the addon on your developer machine also. Move all addon stuff into a temp folder. If you use `FROM $BUILD_FROM` you need set a base image with build args. Normally you can use follow base images: - -- armhf: `homeassistant/armhf-base:latest` -- aarch64: `homeassistant/aarch64-base:latest` -- amd64: `homeassistant/amd64-base:latest` -- i386: `homeassistant/i386-base:latest` - -Use `docker` to build the test addon: `docker build --build-arg BUILD_FROM="homeassistant/amd64-base:latest" -t local/my-test-addon .` - -## Local run - -Create a new folder for data and add a test _options.json_ file. After that you can run your add-on with: `docker run --rm -v /tmp/my_test_data:/data -p PORT_STUFF_IF_NEEDED local/my-test-addon` - -## Logs - -All stdout and stderr are redirected to the Docker logs. The logs can be fetched from the add-on page inside the Hass.io panel in Home Assistant. diff --git a/website/versioned_docs/version-0.92.0/hassio_debugging.md b/website/versioned_docs/version-0.92.0/hassio_debugging.md deleted file mode 100644 index 979994be..00000000 --- a/website/versioned_docs/version-0.92.0/hassio_debugging.md +++ /dev/null @@ -1,64 +0,0 @@ ---- -title: Debugging Hass.io -id: version-0.92.0-hassio_debugging -original_id: hassio_debugging ---- - -> This section is not for end users. End users should use the [SSH add-on] to SSH into Hass.io. This is for developers of Hass.io. Do not ask for support if you are using these options. - -[SSH add-on]: https://www.home-assistant.io/addons/ssh/ - -The following debug tips and tricks are for developers who are running the Hass.io image and are working on the base image. If you use the generic Linux installer script, you should be able to access your host and logs as per your host. - -## SSH access to the host - -### resinOS based Hass.io (deprecated) -Create an `authorized_keys` file containing your public key, and place it in the root of the boot partition of your SD card. See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. Once the device is booted, you can access your device as root over SSH on port 22222. - -### HassOS based Hass.io -Use a USB drive formatted with FAT, ext4, or NTFS and name it CONFIG (case sensitive). Create an `authorized_keys` file (no extension) containing your public key, and place it in the root of the USB drive. See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. From the UI, navigate to the hass.io system page and choose "Import from USB". You can now access your device as root over SSH on port 22222. Alternatively, the file will be imported from the USB when the hass.io device is rebooted. - -> Make sure when you are copying the public key to the root of the USB drive that you rename the file correctly to `authorized_keys` with no `.pub` file extension. - -You should then be able to SSH into your Hass.io device. On Mac/Linux, use: - -``` -ssh root@hassio.local -p 22222 -``` - -You will initially be logged in to Hass.io CLI for HassOS where you can perform normal [CLI functions]. If you need access to the host system use the 'login' command. [Hass.io OS] is a hypervisor for Docker. See the [Hass.io Architecture] documentation for information regarding the Hass.io supervisor. The supervisor offers an API to manage the host and running the Docker containers. Home Assistant itself and all installed addon's run in separate Docker containers. - -[CLI functions]: https://www.home-assistant.io/hassio/commandline/ -[Hass.io OS]: https://github.com/home-assistant/hassos -[Hass.io Architecture]: https://developers.home-assistant.io/docs/en/architecture_hassio.html - -## Checking the logs - -```bash -# Logs from the supervisor service on the Host OS -journalctl -f -u hassos-supervisor.service - -# Hass.io supervisor logs -docker logs hassos_supervisor - -# Home Assistant logs -docker logs homeassistant -``` - -## Accessing the container bash - -```bash -docker exec -it homeassistant /bin/bash -``` - -[windows-keys]: https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-putty-on-digitalocean-droplets-windows-users - -### Generating SSH Keys - -Windows instructions for how to generate and use private/public keys with Putty are [here][windows-keys]. Instead of the droplet instructions, add the public key as per above instructions. - -Alternative instructions, for Mac, Windows and Linux can be found [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#platform-mac). - -Follow steps 1-4 under 'Generating a new SSH key' (The other sections are not applicable to Hass.io and can be ignored.) - -Step 3 in the link above, shows the path to the private key file `id_rsa` for your chosen operating system. Your public key, `id_rsa.pub`, is saved in the same folder. Next, select all text from text box "Public key for pasting into the authorized_keys file" and save it to the root of your USB drive as `authorized_keys`. diff --git a/website/versioned_docs/version-0.92.0/hassio_hass.md b/website/versioned_docs/version-0.92.0/hassio_hass.md deleted file mode 100644 index e8cc6bcc..00000000 --- a/website/versioned_docs/version-0.92.0/hassio_hass.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Hass.io <> Home Assistant integration development -sidebar_label: HASS Integration development -id: version-0.92.0-hassio_hass -original_id: hassio_hass ---- - -These steps will help you connect your local Home Assistant to a remote Hass.io instance. You can then make changes locally to either the Hass.io component or the frontend and test it out against a real instance. - -For this guide, we're going to assume that you have an Hass.io instance up and running. If you don't, you can use the generic installation method to install it inside a [virtual machine](https://github.com/home-assistant/hassio-build/tree/master/install#install-hassio). - -## API Access - -To develop for the frontend, we're going to need API access to the supervisor. - -- Add our developer Add-on repository: https://github.com/home-assistant/hassio-addons-development -- Install the Add-on "Remote API proxy" - -For some API commands you need explicit the Home Assistant API token, but 99% of the functionality work with `Remote API proxy`. This token change some times but you can read the current legal token on host system with: -```sh -$ docker inspect homeassistant | grep HASSIO_TOKEN -``` - - ## Having Home Assistant connect to remote Hass.io - - The connection with the supervisor is hidden inside the host and is only accessible from applications running on the host. So to make it accessible for our Home Assistant instance, we will need to route the connection to our computer running Home Assistant. We're going to do this by forwarding the API with "Remote API proxy" Add-on. - -First, make sure Home Assistant will load the Hass.io component by adding `hassio:` to your `configuration.yaml` file. Next, we will need to tell Hass.io component how to connect to the remote Hass.io instance, we do this by setting the `HASSIO` and `HASSIO_TOKEN` environment variables when starting Home Assistant. Note that the `HASSIO` value is not the same as the one that we saw above and the `HASSIO_TOKEN` is available inside log output of "Remote API Add-on" (This change every restart of this Add-on!). - -```bash -HASSIO=:80 HASSIO_TOKEN= hass -``` - -Voila. Your local Home Assistant installation will now connect to a remote Hass.io instance. - -## Frontend development - -> This requires Home Assistant 0.71 or later. - -We need a couple more steps to do frontend development. First, make sure you have a Home Assistant frontend development set up ([instructions](frontend_index.md)). - -Update the Hass.io component configuration in your `configuration.yaml` to point at the frontend repository: - -```yaml -# configuration.yaml -hassio: - development_repo: /home/paulus/dev/hass/home-assistant-polymer -``` - -To build a local version of the Hass.io panel, go to the frontend repository and run: - -```bash -cd hassio -script/build_hassio -``` - -Now start Home Assistant as discussed in the previous section and it will now connect to the remote Hass.io but show your local frontend. - -We're currently transitioning in how we're building the frontend so we don't have an incremental development mode just yet. For now, after making a local change, run `script/build_hassio` again. diff --git a/website/versioned_docs/version-0.92.1/creating_integration_manifest.md b/website/versioned_docs/version-0.92.1/creating_integration_manifest.md deleted file mode 100644 index 2cb51aaf..00000000 --- a/website/versioned_docs/version-0.92.1/creating_integration_manifest.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: Integration Manifest -sidebar_label: Manifest -id: version-0.92.1-creating_integration_manifest -original_id: creating_integration_manifest ---- - -Since 0.92.0, every integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, except for custom components. - -```json -{ - "domain": "hue", - "name": "Philips Hue", - "documentation": "https://www.home-assistant.io/components/hue", - "dependencies": ["mqtt"], - "codeowners": ["@balloob"], - "requirements": ["aiohue==1.9.1"] -} -``` - -Or a minimal example that you can copy into your project: - -```json -{ - "domain": "your_domain_name", - "name": "Your Intgration", - "documentation": "https://www.example.com", - "dependencies": [], - "codeowners": [], - "requirements": [] -} -``` - -## Domain - -The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. - -## Name - -The name of the integration. - -## Documentation - -The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/` - -## Dependencies - -Dependencies are other Home Assistant integrations that you want Home Assistant to set up successfully prior to the integration being loaded. This can be necessary in case you want to offer functionality from that other integration, like using webhooks or an MQTT connection. - -## Code Owners - -GitHub usernames or team names of people that are responsible for this integration. You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included. - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you running in a virtual environment. This will make sure that all requirements are present at startup. If steps fail, like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is an array of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v3.2.0: `["pychromecast==3.2.0"]`. - -> Because of how Home Assistant installs requirements on demand, actual Python imports of your requirements should be done inside functions instead of at the root level of your Python files. - -### Custom requirements during development & testing - -During the development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using `pychromecast` as an example: - -```bash -pip install pychromecast==3.2.0 --target ~/.homeassistant/deps -hass --skip-pip -``` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is specified in `requirements`. - -If you need to make changes to a requirement to support your component, it's also possible to install a development version of the requirement using `pip install -e`: - -```bash -git clone https://github.com/balloob/pychromecast.git -pip install -e ./pychromecast -hass --skip-pip -``` diff --git a/website/versioned_docs/version-0.92.1/development_checklist.md b/website/versioned_docs/version-0.92.1/development_checklist.md deleted file mode 100644 index 6da2ea05..00000000 --- a/website/versioned_docs/version-0.92.1/development_checklist.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Development Checklist -sidebar_label: Introduction -id: version-0.92.1-development_checklist -original_id: development_checklist ---- - - -Before you commit any changes, check your work against these requirements: - -- All communication to external devices or services must be wrapped in an external Python library hosted on [pypi](https://pypi.python.org/pypi). -- New dependencies are added to `requirements_all.txt` (if applicable), using `python3 -m script.gen_requirements_all` -- New codeowners are added to `CODEOWNERS` (if applicable), using `python3 -m script.hassfest` -- The `.coveragerc` file is updated to exclude your platform if there are no tests available or your new code uses a third-party library for communication with the device, service, or sensor -- Documentation is developed for [home-assistant.io](https://home-assistant.io/) - * Visit the [website documentation](https://www.home-assistant.io/developers/documentation/) for more information about contributing to [home-assistant.io](https://github.com/home-assistant/home-assistant.github.io). diff --git a/website/versioned_docs/version-0.92.1/entity_fan.md b/website/versioned_docs/version-0.92.1/entity_fan.md deleted file mode 100644 index ecbaf1f9..00000000 --- a/website/versioned_docs/version-0.92.1/entity_fan.md +++ /dev/null @@ -1,98 +0,0 @@ ---- -title: Fan Entity -sidebar_label: Fan -id: version-0.92.1-entity_fan -original_id: entity_fan ---- - -A fan entity is a device that controls the different vectors of your fan such as speed, direction and oscillation. Derive enitity platforms from ['homeassistant.components.fan.FanDevice'](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/fan/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| current_direction | str | None | Return the current direction of the fan | -|is_on| boolean | None |Return true if the entity is on | -| speed | str | None | Return the current speed | -| speed_list | list | None| Get the list of available speeds | -| state_attributes | dict | None | Return optional state attributes | -| supported_features | int | None | Flag supported features | - - -## Supported Features - -| Constant | Description | -|----------|--------------------------------------| -| 'SUPPORT_DIRECTION' | The fan supports changing the direction of it. -| 'SUPPORT_SET_SPEED' | The fan supports setting the speed. -| 'SUPPORT_OSCILLATE' | The fan supports oscillation. - - - -## Methods - -### Set direction - -Only implement this method if the flag `SUPPORT_DIRECTION` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def set_direction(self, direction: str) -> None: - """Set the direction of the fan.""" - - async def async_set_direction(self, direction: str): - """Set the direction of the fan.""" -``` - -### Set speed - -Only implement this method if the flag `SUPPORT_SET_SPEED` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def set_speed(self, speed: str) -> None: - """Set the speed of the fan.""" - - async def async_set_speed(self, speed: str): - """Set the speed of the fan.""" -``` - -### Turn on - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def turn_on(self, speed: str = None, **kwargs) -> None: - """Turn on the fan.""" - - async def async_turn_on(self, speed: str = None, **kwargs): - """Turn on the fan.""" -``` - -### Oscillate - -Only implement this method if the flag `SUPPORT_OSCILLATE` is set. - -```python -class FanEntity(ToggleEntity): - # Implement one of these methods. - - def oscillate(self, oscillating: bool) -> None: - """Oscillate the fan.""" - - def async_oscillate(self, oscillating: bool): - """Oscillate the fan.""" -``` - - - - - - diff --git a/website/versioned_docs/version-0.92.1/entity_light.md b/website/versioned_docs/version-0.92.1/entity_light.md deleted file mode 100644 index 5414ba77..00000000 --- a/website/versioned_docs/version-0.92.1/entity_light.md +++ /dev/null @@ -1,63 +0,0 @@ ---- -title: Light Entity -sidebar_label: Light -id: version-0.92.1-entity_light -original_id: entity_light ---- - - -A light entity is a device that controls the brightness, RGB value,color temperature and effects of a light source. - -## Properties - -| Name | Type | Default | Description -| ---- | ---- | ---- | ---- -| brightness | int | None | Return the brightness of this light between 0..255 -| color_temp | int | None | Return the CT color value in mireds. -| effect | String | None | Return the current effect. -| effect_list | list | None | Return the list of supported effects. -| hs_color | list | None | Return the hue and saturation color value [float, float]. -| is_on | bool | bool | Returns if the light entity is on or not. -| max_minreds | int | int | Return the warmest color_temp that this light supports. -| min_mireds | int | int | Return the coldest color_temp that this light supports. -| supported_features | int | int | Flag supported features. -| white_value | int | None | Return the white value of this light between 0..255. - - -## Support Feature -| Constant | Description -|----------|----------------------- -| `SUPPORT_BRIGHTNESS` | Controls the brightness of a light source -| `SUPPORT_COLOR` | Controls the color a light source shows -| `SUPPORT_COLOR_TEMP` | Controls the representation a light source shows based on temperature -| `SUPPORT_EFFECT` | Controls the effect a light source shows -| `SUPPORT_FLASH` | Controls the duration of a flash a light source shows -| `SUPPORT_TRANSITION` | Controls the duration of transitions between color and effects -| `SUPPORT_WHITE_VALUE` | Controls the white light a light source shows. - -## Methods - -# Turn on Light Device - -```python -class MyLightDevice(LightDevice): - def turn_on(self, **kwargs): - """Turn the device on.""" - - async def async_turn_on(self, **kwargs): - """Turn device on.""" - -``` - -# Turn Off Light Device - -```python -class MyLightDevice(LightDevice): - - def turn_off(self, **kwargs): - """Turn the device off.""" - - async def async_turn_off(self, **kwargs): - """Turn device off.""" - -``` diff --git a/website/versioned_docs/version-0.92.1/entity_media_player.md b/website/versioned_docs/version-0.92.1/entity_media_player.md deleted file mode 100644 index a6b5f3b2..00000000 --- a/website/versioned_docs/version-0.92.1/entity_media_player.md +++ /dev/null @@ -1,76 +0,0 @@ ---- -title: Media Player Entity -sidebar_label: Media Player -id: version-0.92.1-entity_media_player -original_id: entity_media_player ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| sound_mode | string | None | The current sound mode of the media player -| sound_mode_list | list | None | Dynamic list of available sound modes (set by platform, empty means sound mode not supported) -| source | string | None | The currently selected input source for the media player. -| source_list | list | None | The list of possible input sources for the media player. (This list should contain human readable names, suitible for frontend display) -| media_image_url | string | None | URL that represents the current image. -| media_image_remotely_accessible | boolean | False | Return `True` if property `media_image_url` is accessible outside of the home network. -| device_class | string | `None` | Type of binary sensor. - -## Methods -### Select sound mode -Optional. Switch the sound mode of the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - def async_select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - -### Select source -Optional. Switch the selected input source for the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_source(self, source): - """Select input source.""" - - def async_select_source(self, source): - """Select input source.""" - -### Mediatype -Required. Returns one of the defined constants from the below list that matches the mediatype - -| CONST | -|-------| -|MEDIA_TYPE_MUSIC| -|MEDIA_TYPE_TVSHOW| -|MEDIA_TYPE_MOVIE| -|MEDIA_TYPE_VIDEO| -|MEDIA_TYPE_EPISODE| -|MEDIA_TYPE_CHANNEL| -|MEDIA_TYPE_PLAYLIST| -|MEDIA_TYPE_IMAGE| -|MEDIA_TYPE_URL| -|MEDIA_TYPE_GAME| - - class MyMediaPlayer(MediaPlayerDevice): - # Implement the following method. - - def media_content_type(self): - """Content type of current playing media.""" - -### Available device classes -Optional. What type of media device is this. It will possibly map to google device types. -| Value | Description -| ----- | ----------- -| tv | Device is a television type device. -| speaker | Device is speakers or stereo type device. diff --git a/website/versioned_docs/version-0.92.1/internationalization_custom_component_localization.md b/website/versioned_docs/version-0.92.1/internationalization_custom_component_localization.md deleted file mode 100644 index a3aa99e3..00000000 --- a/website/versioned_docs/version-0.92.1/internationalization_custom_component_localization.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: Custom Component Localization -id: version-0.92.1-internationalization_custom_component_localization -original_id: internationalization_custom_component_localization ---- - -## Translation Strings -Unlike localized strings merged in the `home-assistant` repository, custom components cannot take advantage of Lokalise for user submitted translations. However, custom component authors can still include translations with their components. These will be read from the `.translations` directory, adjacent to the component source. They are named `..json`, e.g., for the German translation of a sensor `sensor.de.json`, unless the translation is for the custom component only, in which case the file is simply named `.json` in the `.translations` directory. - -These files follow the same formatting as [backend translation string files](internationalization_backend_localization.md), but a copy will exist for each translated language. - -The language codes follow the [BCP47](https://tools.ietf.org/html/bcp47) format. The [frontend translation files](https://github.com/home-assistant/home-assistant-polymer/tree/master/translations) can also be referred to if you are unsure of the correct language code to use. - -The frontend will serve these files after Home Assistant is restarted. diff --git a/website/versioned_docs/version-0.93.0/auth_permissions.md b/website/versioned_docs/version-0.93.0/auth_permissions.md deleted file mode 100644 index f3fd021b..00000000 --- a/website/versioned_docs/version-0.93.0/auth_permissions.md +++ /dev/null @@ -1,273 +0,0 @@ ---- -title: Permissions -id: version-0.93.0-auth_permissions -original_id: auth_permissions ---- - -> This is an experimental feature that is not enabled or enforced yet - -Permissions limit the things a user has access to or can control. Permissions are attached to groups, of which a user can be a member. The combined permissions of all groups a user is a member of decides what a user can and cannot see or control. - -Permissions do not apply to the user that is flagged as "owner". This user will always have access to everything. - -## General permission structure - -Policies are dictionaries that at the root level consist of different categories of permissions. In the current implementation this is limited to just entities. - -```python -{ - "entities": … -} -``` - -Each category can further split into subcategories that describe parts of that category. - -```python -{ - "entities": { - "domains": …, - "entity_ids": … - } -} -``` - -If a category is omitted, the user will not have permission to that category. - -When defining a policy, any dictionary value at any place can be replaced with `True` or `None`. `True` means that permission is granted and `None` means use default, which is deny access. - -## Entities - -Entity permissions can be set on a per entity and per domain basis using the subcategories `entity_ids`, `device_ids`, `area_ids` and `domains`. You can either grant all access by setting the value to `True`, or you can specify each entity individually using the "read", "control", "edit" permissions. - -The system will return the first matching result, based on the order: `entity_ids`, `device_ids`, `area_ids`, `domains`, `all`. - -```json -{ - "entities": { - "domains": { - "switch": true - }, - "entity_ids": { - "light.kitchen": { - "read": true, - "control": true - } - } - } -} -``` - -## Merging policies - -If a user is a member of multiple groups, the groups permission policies will be combined into a single policy at runtime. When merging policies, we will look at each level of the dictionary and compare the values for each source using the following methodology: - -1. If any of the values is `True`, the merged value becomes `True`. -2. If any value is a dictionary, the merged value becomes a dictionary created by recursively checking each value using this methodology. -3. If all values are `None`, the merged value becomes `None`. - -Let's look at an example: - -```python -{ - "entities": { - "entity_ids": { - "light.kitchen": True - } - } -} -``` - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -Once merged becomes - -```python -{ - "entities": { - "entity_ids": True - } -} -``` - -## Checking permissions - -We currently have two different permission checks: can the user do the read/control/edit operation on an entity, and is the user an admin and thus allowed to change this configuration setting. - -Certain APIs will always be accessible to all users, but might offer a limited scope based on the permissions, like rendering a template. - -### Checking permissions - -To check a permission, you will need to have access to the user object. Once you have the user object, checking the permission is easy. - -```python -from homeassistant.exceptions import Unauthorized -from homeasistant.permissions.const import ( - POLICY_READ, POLICY_CONTROL, POLICY_EDIT -) - -# Raise error if user is not an admin -if not user.is_admin: - raise Unauthorized() - - -# Raise error if user does not have access to control an entity -# Available policies: POLICY_READ, POLICY_CONTROL, POLICY_EDIT -if not user.permissions.check_entity(entity_id, POLICY_CONTROL): - raise Unauthorized() -``` - -### The context object - -All service calls, fired events and states in Home Assistant have a context object. This object allows us to attribute changes to events and services. These context objects also contain a user id, which is used for checking the permissions. - -It's crucial for permission checking that actions taken on behalf of the user are done with a context containing the user ID. If you are in a service handler, you should re-use the incoming context `call.context`. If you are inside a WebSocket API or Rest API endpoint, you should create a context with the correct user: - -```python -from homeassistant.core import Context - -await hass.services.async_call('homeassistant', 'stop', context=Context( - user_id=user.id -), blocking=True) -``` - -### If a permission check fails - -When you detect an anauthorized action, you should raise the `homeassistant.exceptions.Unauthorized` exception. This exception will cancel the current action and notifies the user that their action is unauthorized. - -The `Unauthorized` exception has various parameters, to identify the permission check that failed. All fields are optional. - -| # Not all actions have an ID (like adding config entry) -| # We then use this fallback to know what category was unauth - - -| Parameter | Description -| --------- | ----------- -| context | The context of the current call. -| user_id | The user ID that we tried to operate on. -| entity_id | The entity ID that we tried to operate on. -| config_entry_id | The config entry ID that we tried to operate on. -| perm_category | The permission category that we tested. Only necessary if we don't have an object ID that the user tried to operate on (like when we create a config entry). -| permission | The permission that we tested, ie `POLICY_READ`. - -### Securing a service call handler - -Service calls allow a user to control entities or with the integration as a whole. A service call uses the attached context to see which user invoked the command. Because context is used, it is important that you also pass the call context to all service calls. - -All services that are registered via the entity component (`component.async_register_entity_service()`) will automatically have their permissions checked. - -#### Checking entity permissions - -Your service call handler will need to check the permissions for each entity that it will act on. - -```python -from homeassistant.exceptions import Unauthorized, UnknownUser -from homeassistant.auth.permissions.const import POLICY_CONTROL - -async def handle_entity_service(call): - """Handle a service call.""" - entity_ids = call.data['entity_id'] - - for entity_id in entity_ids: - if call.context.user_id: - user = await hass.auth.async_get_user(call.context.user_id) - - if user is None: - raise UnknownUser( - context=call.context, - entity_id=entity_id, - permission=POLICY_CONTROL, - ) - - if not user.permissions.check_entity(entity_id, POLICY_CONTROL): - raise Unauthorized( - context=call.context, - entity_id=entity_id, - permission=POLICY_CONTROL, - ) - - # Do action on entity - - -async def async_setup(hass, config): - hass.services.async_register(DOMAIN, 'my_service', handle_entity_service) - return True -``` - -#### Checking admin permission - -Starting Home Assistant 0.90, there is a special decorator to help protect -services that require admin access. - -```python -# New in Home Assistant 0.90 -async def handle_admin_service(call): - """Handle a service call.""" - # Do admin action - - -async def async_setup(hass, config): - hass.helpers.service.async_register_admin_service( - DOMAIN, 'my_service', handle_admin_service, vol.Schema({}) - ) - return True -``` - -### Securing a REST API endpoint - -```python -from homeassistant.core import Context -from homeassistant.components.http.view import HomeAssistantView -from homeassistant.exceptions import Unauthorized - - -class MyView(HomeAssistantView): - """View to handle Status requests.""" - - url = '/api/my-component/my-api' - name = 'api:my-component:my-api' - - async def post(self, request): - """Notify that the API is running.""" - hass = request.app['hass'] - user = request['hass_user'] - - if not user.is_admin: - raise Unauthorized() - - hass.bus.async_fire('my-component-api-running', context=Context( - user_id=user.id - )) - - return self.json_message("Done.") -``` - -### Securing a Websocket API endpoint - -Verifying permissions in a Websocket API endpoint can be done by accessing the -user via `connection.user`. If you need to check admin access, you can use the -built-in `@require_admin` decorator. - -```python -from homeassistant.compnents import websocket_api - - -async def async_setup(hass, config): - hass.components.websocket_api.async_register_command(websocket_create) - return True - - -@websocket_api.require_admin -@websocket_api.async_response -@websocket_api.websocket_command({ - vol.Required('type'): 'my-component/my-action', -}) -async def websocket_create(hass, connection, msg): - """Create a user.""" - # Do action -``` diff --git a/website/versioned_docs/version-0.93.0/creating_integration_manifest.md b/website/versioned_docs/version-0.93.0/creating_integration_manifest.md deleted file mode 100644 index da3c4562..00000000 --- a/website/versioned_docs/version-0.93.0/creating_integration_manifest.md +++ /dev/null @@ -1,79 +0,0 @@ ---- -title: Integration Manifest -sidebar_label: Manifest -id: version-0.93.0-creating_integration_manifest -original_id: creating_integration_manifest ---- - -Since 0.92.0, every integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, except for custom components. - -```json -{ - "domain": "hue", - "name": "Philips Hue", - "documentation": "https://www.home-assistant.io/components/hue", - "dependencies": ["mqtt"], - "codeowners": ["@balloob"], - "requirements": ["aiohue==1.9.1"] -} -``` - -Or a minimal example that you can copy into your project: - -```json -{ - "domain": "your_domain_name", - "name": "Your Integration", - "documentation": "https://www.example.com", - "dependencies": [], - "codeowners": [], - "requirements": [] -} -``` - -## Domain - -The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. - -## Name - -The name of the integration. - -## Documentation - -The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/` - -## Dependencies - -Dependencies are other Home Assistant integrations that you want Home Assistant to set up successfully prior to the integration being loaded. This can be necessary in case you want to offer functionality from that other integration, like using webhooks or an MQTT connection. - -## Code Owners - -GitHub usernames or team names of people that are responsible for this integration. You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included. - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you running in a virtual environment. This will make sure that all requirements are present at startup. If steps fail, like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is an array of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v3.2.0: `["pychromecast==3.2.0"]`. - -> Because of how Home Assistant installs requirements on demand, actual Python imports of your requirements should be done inside functions instead of at the root level of your Python files. - -### Custom requirements during development & testing - -During the development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using `pychromecast` as an example: - -```bash -pip install pychromecast==3.2.0 --target ~/.homeassistant/deps -hass --skip-pip -``` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is specified in `requirements`. - -If you need to make changes to a requirement to support your component, it's also possible to install a development version of the requirement using `pip install -e`: - -```bash -git clone https://github.com/balloob/pychromecast.git -pip install -e ./pychromecast -hass --skip-pip -``` diff --git a/website/versioned_docs/version-0.93.0/development_testing.md b/website/versioned_docs/version-0.93.0/development_testing.md deleted file mode 100644 index c4d7f39a..00000000 --- a/website/versioned_docs/version-0.93.0/development_testing.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Testing your code -id: version-0.93.0-development_testing -original_id: development_testing ---- - -As it states in the [Style guidelines section](development_guidelines.md) all code is checked to verify the following: - -- All the unit tests pass -- All code passes the checks from the linting tools - -Local testing is done using Tox, which has been installed as part of running `script/setup` in the [virtual environment](development_environment.md). To start the tests, activate the virtual environment and simply run the command: - -```bash -$ tox -``` -**Important:** Run `tox` before you create your pull request to avoid annoying fixes. - -Running Tox will run unit tests against the locally available Pythons, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one tox target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py36` runs unit tests only on Python 3.6. - -Tox uses virtual environments under the hood to create isolated testing environments. The tox virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell Tox to recreate the virtual environments. - -OSX users may see an `Error creating virtualenv` when runnng `tox`. If this occurs, install the [tox-venv](https://pypi.org/project/tox-venv/) package using the command `pip install tox-venv` and try again. - -### Adding new dependencies to test environment - -If you are working on tests for a component or platform and you need the dependencies available inside the Tox environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments. - -### Running single tests using Tox - -You can pass arguments via Tox to py.test to be able to run single test suites or test files. Replace `py36` with the Python version that you use. - -```bash -# Stop after the first test fails -$ tox -e py36 -- tests/test_core.py -x -# Run test with specified name -$ tox -e py36 -- tests/test_core.py -k test_split_entity_id -# Fail a test after it runs for 2 seconds -$ tox -e py36 -- tests/test_core.py --timeout 2 -# Show the 10 slowest tests -$ tox -e py36 -- tests/test_core.py --duration=10 -``` - -### Testing outside of Tox - -Running tox will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without Tox, you'll need to install the test dependencies into your Python environment: - -```bash -$ pip3 install -r requirements_test_all.txt -c homeassistant/package_constraints.txt -``` - -Now that you have all test dependencies installed, you can run tests on individual files: - -```bash -$ flake8 homeassistant/core.py -$ pylint homeassistant/core.py -$ pydocstyle homeassistant/core.py -$ py.test tests/test_core.py -``` - -You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script: - -```bash -$ script/lint -``` - -### Preventing Linter Errors - -Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them! - -```bash -$ pip3 install flake8 flake8-docstrings -$ flake8 --install-hook=git -``` - -The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8. - -### Notes on PyLint and PEP8 validation - -If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member. diff --git a/website/versioned_docs/version-0.93.0/documentation_create_page.md b/website/versioned_docs/version-0.93.0/documentation_create_page.md deleted file mode 100644 index d5630415..00000000 --- a/website/versioned_docs/version-0.93.0/documentation_create_page.md +++ /dev/null @@ -1,133 +0,0 @@ ---- -title: Create a new page -id: version-0.93.0-documentation_create_page -original_id: documentation_create_page ---- - -For a platform or component page, the fastest way is to make a copy of an existing page and edit it. The [Component overview](https://www.home-assistant.io/components/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages. - -Please honor the [Standards](documentation_standards.md) we have for the documentation. - -If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers. - -```text ---- -layout: page -title: "Awesome Sensor" -description: "home-assistant.io web presence" -date: 2015-06-17 08:00 -sidebar: true -comments: false -sharing: true -footer: true -ha_release: "0.38" -ha_category: Sensor -ha_iot_class: "Local Polling" -ha_qa_scale: silver ---- - -Content... Written in markdown. - -### {% linkable_title Linkable Header %} -... -``` - -Please keep in mind that if the `date:` entry is in the future then the page will not show up. - -Additional keys for the file header: - -- `logo`: Please check the separate section below. -- `ha_release`: The release when the integration was included, e.g., "0.38". If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`. -- `ha_category`: This entry is used to group the integration on the [Components overview](https://www.home-assistant.io/components/). -- `ha_iot_class`: [IoT class](https://www.home-assistant.io/blog/2016/02/12/classifying-the-internet-of-things) is the classifier for the device's behavior. -- `ha_qa_scale`: [Quality scale](https://www.home-assistant.io/docs/quality_scale/) is the representation of the integration's quality. - -There are [pre-defined variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation. - -A couple of points to remember: - -- Document the needed steps to retrieve API keys or access token for the third party service or device if needed. -- Add screenshots to support the user where it makes sense. -- Add the type of the device(s) (incl. firmware) you have tested when you know that there are multiple out there. - -### Configuration - -Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file. - -The **Configuration Variables** section must use the `{% configuration %} ... {% endconfiguration %}` tag. - -```text -{% configuration %} -api_key: - description: The API key to access the service. - required: true - type: string -name: - description: Name to use in the frontend. - required: false - default: The default name to use in the frontend. - type: string -monitored_conditions: - description: Conditions to display in the frontend. - required: true - type: map - keys: - weather: - description: A human-readable text summary. - temperature: - description: The current temperature. -{% endconfiguration %} -``` - -Available keys: - -- **`description:`**: That the variable is about. -- **`required:`**: If the variable is required. - -```text -required: true #=> Required -required: false #=> Optional -required: inclusive #=> Inclusive -required: exclusive #=> Exclusive -required: any string here #=> Any string here -``` -- **`type:`**: The type of the variable. Allowed entries: `boolean`, `string`, `integer`, `float`, `time`, `template`, `device_class`, `icon` or `map`/`list` (for a list of entries). For multiple possibilities use `[string, integer]`. If you use `map`/`list` then should define `keys:` (see the [`template` sensor](https://www.home-assistant.io/components/sensor.template/) for an example). If you use `boolean`, then `default:` must be defined. -- **`default:`**: The default value for the variable. - -### Embedding Code - -You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in back-ticks. - -When you're writing code that is to be executed on the terminal, prefix it with `$`. - -### Templates - -For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) [Jinja](http://jinja.pocoo.org/) is used. Check the [Documentation Standards](documentation_standards.md) for further details. - -If you are don't escape templates then they will be rendered and appear blank on the website. - -### HTML - -The direct usage of HTML is supported but not recommended. The note boxes are an exception. - -```html -

- You need to enable telnet on your router. -

-``` - -### Images, icons and logos - -The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent. - -| Type | Location | -| :----------- |:----------------------------------------------| -| logos | source/images/supported_brands | -| blog | source/images/blog | -| screenshots | source/images/components | - -Not everything (product, component, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/). - -### Linking From The Sidebar - -If you are adding a new page that requires linking from the sidebar, you need to edit the `docs_navigation.html` file in `source/_includes/asides/docs_navigation.html`. diff --git a/website/versioned_docs/version-0.93.0/entity_index.md b/website/versioned_docs/version-0.93.0/entity_index.md deleted file mode 100644 index 21f75a10..00000000 --- a/website/versioned_docs/version-0.93.0/entity_index.md +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Entity -sidebar_label: Introduction -id: version-0.93.0-entity_index -original_id: entity_index ---- - -Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating. - -Below is an example switch entity that keeps track of their state in memory. - -```python -from homeassistant.components.switch import SwitchDevice - -class MySwitch(SwitchDevice): - - def __init__(self): - self._is_on = False - - @property - def name(self): - """Name of the device.""" - return 'My Switch' - - @property - def is_on(self): - """If the switch is currently on or off.""" - return self._is_on - - def turn_on(self, **kwargs): - """Turn the switch on.""" - self._is_on = True - - def turn_off(self, **kwargs): - """Turn the switch off.""" - self._is_on = False -``` - -That's all there is to it to build a switch entity! Continue reading to learn more or check out the [video tutorial](https://youtu.be/Cfasc9EgbMU?t=737). - -## Updating the entity - -An entity represents a device. There are various strategies to keep your entity in sync with the state of the device, the most popular one being polling. - -### Polling - -With polling, Home Assistant will ask the entity from time to time (depending on the update interval of the component) to fetch the latest state. Home Assistant will poll an entity when the `should_poll` property returns `True` (the default value). You can either implement your update logic using `update()` or the async method `async_update()`. This method should fetch the latest state from the device and store it in an instance variable for the properties to return it. - -### Subscribing to updates - -When you subscribe to updates, your code is responsible for letting Home Assistant know that an update is available. Make sure you have the `should_poll` property return `False`. - -Whenever you receive new state from your subscription, you can tell Home Assistant that an update is available by calling `schedule_update_ha_state()` or async callback `async_schedule_update_ha_state()`. Pass in the boolean `True` to the method if you want Home Assistant to call your update method before writing the update to Home Assistant. - -## Generic properties - -The entity base class has a few properties that are common among all entities in Home Assistant. These can be added to any entity regardless of the type. All these properties are optional and don't need to be implemented. - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| assumed_state | boolean | `False` | Return `True` if the state is based on our assumption instead of reading it from the device. -| available | boolean | `True` | Indicate if Home Assistant is able to read the state and control the underlying device. -| device_state_attributes | dict | `None` | Extra information to store in the state machine. It needs to be information that further explains the state, it should not be static information like firmware version. See [below](entity_index.md#standard_attributes) for details of standard attributes. -| entity_picture | URL | `None` | Url of a picture to show for the entity. -| name | string | `None` | Name of the entity -| should_poll | boolean | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](#methods). -| unique_id | string | `None` | A unique identifier for this entity. Needs to be unique within a platform (ie `light.hue`). Should not be configurable by the user or be changeable. [Learn more.](entity_registry_index.md#unique-id-requirements) - -## Advanced properties - -The following properties are also available on entities. However, they are for advanced use only and should be used with caution. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| force_update | boolean | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine. -| hidden | boolean | `False` | Indicate if the entity should not be shown on the frontend. -| icon | icon | `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all devices. - -## Standard attributes - -The following `device_state_attributes` are considered standard and should follow the convention below. The constant should be imported from `homeassistant/const.py`. - -| Name | Type | Unit | Constant | Description -| ---- | ---- | ---- | -------- | ----------- -| battery_charging | boolean | N/A | `ATTR_BATTERY_CHARGING` | Battery charging status of the entity, shown as a boolean `true` or `false`. If charging is not supported, then this attribute should not be created. -| battery_level | integer | % | `ATTR_BATTERY_LEVEL` | Battery level of the entity, shown as an integer percentage between 0-100. - -## Lifecycle hooks - -Use these lifecycle hooks to execute code when certain events happen to the entity. All lifecycle hooks are async methods. - -### `async_added_to_hass()` - -Called when an entity has their entity_id and hass object assigned, before it is written to the state machine for the first time. Example uses: restore the state, subscribe to updates or set callback/dispatch function/listener. - -### `async_will_remove_from_hass()` - -Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates. - -## Changing the entity model - -If you want to add a new feature to an entity or any of its subtypes (light, switch, etc), you will need to propose it first in our [architecture repo](https://github.com/home-assistant/architecture/issues). Only additions will be considered that are common features among various vendors. diff --git a/website/versioned_docs/version-0.93.0/entity_media_player.md b/website/versioned_docs/version-0.93.0/entity_media_player.md deleted file mode 100644 index c47139eb..00000000 --- a/website/versioned_docs/version-0.93.0/entity_media_player.md +++ /dev/null @@ -1,77 +0,0 @@ ---- -title: Media Player Entity -sidebar_label: Media Player -id: version-0.93.0-entity_media_player -original_id: entity_media_player ---- - -> This entry is incomplete. Contribution welcome. - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| sound_mode | string | None | The current sound mode of the media player -| sound_mode_list | list | None | Dynamic list of available sound modes (set by platform, empty means sound mode not supported) -| source | string | None | The currently selected input source for the media player. -| source_list | list | None | The list of possible input sources for the media player. (This list should contain human readable names, suitible for frontend display) -| media_image_url | string | None | URL that represents the current image. -| media_image_remotely_accessible | boolean | False | Return `True` if property `media_image_url` is accessible outside of the home network. -| device_class | string | `None` | Type of binary sensor. - -## Methods -### Select sound mode -Optional. Switch the sound mode of the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - - def async_select_sound_mode(self, sound_mode): - """Switch the sound mode of the entity.""" - -### Select source -Optional. Switch the selected input source for the media player. - - class MyMediaPlayer(MediaPlayerDevice): - # Implement one of these methods. - - def select_source(self, source): - """Select input source.""" - - def async_select_source(self, source): - """Select input source.""" - -### Mediatype -Required. Returns one of the defined constants from the below list that matches the mediatype - -| CONST | -|-------| -|MEDIA_TYPE_MUSIC| -|MEDIA_TYPE_TVSHOW| -|MEDIA_TYPE_MOVIE| -|MEDIA_TYPE_VIDEO| -|MEDIA_TYPE_EPISODE| -|MEDIA_TYPE_CHANNEL| -|MEDIA_TYPE_PLAYLIST| -|MEDIA_TYPE_IMAGE| -|MEDIA_TYPE_URL| -|MEDIA_TYPE_GAME| -|MEDIA_TYPE_APP| - - class MyMediaPlayer(MediaPlayerDevice): - # Implement the following method. - - def media_content_type(self): - """Content type of current playing media.""" - -### Available device classes -Optional. What type of media device is this. It will possibly map to google device types. -| Value | Description -| ----- | ----------- -| tv | Device is a television type device. -| speaker | Device is speakers or stereo type device. diff --git a/website/versioned_docs/version-0.93.0/entity_registry_index.md b/website/versioned_docs/version-0.93.0/entity_registry_index.md deleted file mode 100644 index 9c032f7c..00000000 --- a/website/versioned_docs/version-0.93.0/entity_registry_index.md +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Entity Registry -sidebar_label: Introduction -id: version-0.93.0-entity_registry_index -original_id: entity_registry_index ---- - -The entity registry is a registry where Home Assistant keeps track of entities. Any entity that is added to Home Assistant and has a unique ID will be registered in the registry. - -Being registered has the advantage that the same entity will always get the same entity ID. It will also prevent other entities from using that entity ID. - -A user is also able to override the name of an entity in the entity registry. When set, the name of the entity registry is used in favor of the name the device might give itself. - -## Unique ID requirements - -An entity is looked up in the registry based on a combination of the plaform type (e.g., `light`), and the integration name (domain) (ie hue) and the unique ID of the entity. It is therefore very important that the unique ID is unique! It is also important that it is not possible for the user to change the unique ID, because that means it will lose all its settings related to it. - -Good sources for a unique ID: - - - Serial number of a device - - MAC address of a device - - latitude/longitude - -If a device has a single serial but provides multiple entities, combine the serial with unique identifiers for the entities. For example, if a device measures both temperature and humidity, you can uniquely identify the entities using `{serial}-{sensor_type}`. diff --git a/website/versioned_docs/version-0.93.0/entity_switch.md b/website/versioned_docs/version-0.93.0/entity_switch.md deleted file mode 100644 index dce11b1b..00000000 --- a/website/versioned_docs/version-0.93.0/entity_switch.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -title: Switch Entity -sidebar_label: Switch -id: version-0.93.0-entity_switch -original_id: entity_switch ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| is_on | boolean | **Required** | If the switch is currently on or off. -| current_power_w | float | `None` | The current power usage in W. -| today_energy_kwh | float | `None` | Total energy usage in kWh. -| is_standby | boolean | `None` | Indicate if the device connected to the switch is currently in standby. - -## Methods - -### Turn On - -Turn the switch on. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def turn_on(self, **kwargs) -> None: - """Turn the entity on.""" - - async def async_turn_on(self, **kwargs): - """Turn the entity on.""" - -``` - -### Turn Off - -Turn the switch off. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def turn_off(self, **kwargs): - """Turn the entity off.""" - - async def async_turn_off(self, **kwargs): - """Turn the entity off.""" -``` - -### Toggle - -Optional. If not implemented will default to checking what method to call using the `is_on` property. - -```python -class MySwitch(SwitchDevice): - # Implement one of these methods. - - def toggle(self, **kwargs): - """Toggle the entity.""" - - async def async_toggle(self, **kwargs): - """Toggle the entity.""" -``` - -### Available device classes -Optional. What type of device this. It will possibly map to google device types. -| Value | Description -| ----- | ----------- -| outlet | Device is an outlet for power. -| switch | Device is switch for some type of entity. diff --git a/website/versioned_docs/version-0.93.0/hassio_addon_index.md b/website/versioned_docs/version-0.93.0/hassio_addon_index.md deleted file mode 100644 index 99ebfbd5..00000000 --- a/website/versioned_docs/version-0.93.0/hassio_addon_index.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -title: Developing an add-on -sidebar_label: Introduction -id: version-0.93.0-hassio_addon_index -original_id: hassio_addon_index ---- - -Add-ons for Hass.io allow the user to extend the functionality around Home Assistant. This can be running an application that Home Assistant can integrate with (like an MQTT broker) or to share the configuration via Samba for easy editing from other computers. Add-ons can be configured via the Hass.io panel in Home Assistant. - -Under the hood, add-ons are Docker images published in [Docker Hub](https://hub.docker.com/). Developers can create [GitHub](https://github.com) repositories that contain multiple references to add-ons for easy sharing with the community. - -1. [Tutorial: Making your first add-on](hassio_addon_tutorial.md) -1. [Configuration](hassio_addon_config.md) -1. [Communication](hassio_addon_communication.md) -1. [Local Testing](hassio_addon_testing.md) -1. [Publishing](hassio_addon_publishing.md) -1. [Presentation](hassio_addon_presentation.md) -1. [Repositories](hassio_addon_repository.md) -1. [Security](hassio_addon_security.md) - - -Useful links: - -* [Hass.io Supervisor](https://github.com/home-assistant/hassio) -* [Hass.io Core Add-ons](https://github.com/home-assistant/hassio-addons) -* [Hass.io Build environment](https://github.com/home-assistant/hassio-build) -* [Hass.io base images](https://github.com/home-assistant/hassio-base) -* [Hass.io Builder](https://github.com/home-assistant/hassio-builder) -* [Hass.io community Add-ons](https://github.com/hassio-addons) -* [HassOS embedded Linux](https://github.com/home-assistant/hassos) -* [Home Assistant Dockerfile](https://github.com/home-assistant/hassio-homeassistant) diff --git a/website/versioned_docs/version-0.93.0/hassio_addon_security.md b/website/versioned_docs/version-0.93.0/hassio_addon_security.md deleted file mode 100644 index e2dca0fe..00000000 --- a/website/versioned_docs/version-0.93.0/hassio_addon_security.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -title: Add-on security -id: version-0.93.0-hassio_addon_security -original_id: hassio_addon_security ---- - -Hass.io rates every add-on based on the wanted rights. An add-on with a rating of 6 is very secure. If an add-on has a rating of 1, you shouldn't run this add-on unless you are 100% sure that you can trust the source. - -## API Role - -For access to Hass.io API you need define a role or you run in default mode. This is only required for Hass.io API not Home Assistant proxy. Any of the roles already have access to the default API calls, and do not require any additional settings. - -### Available Roles - -| Role | Description | -|------|-------------| -| default | Have access to all `info` calls | -| homeassistant | Can access all Home Assistant API endpoints | -| backup | Can access all snapshot API endpoints | -| manager | Is for Add-ons that run CLIs and need extended rights | -| admin | Have access to every API call. That is the only one they can disable/enable the Add-on protection mode | - -## Protection - -Default, all add-ons run in protection enabled mode. This mode prevents the add-on from getting any rights on the system. If an add-on requires more rights, you can disable this protection via the API add-on options for that add-on. But be careful, an add-on with disabled protection can destroy your system! - -## Making a secure add-on - -As a developer, follow the following best practices to make your add-on secure: - -- Don't run on host network -- Create an AppArmor profile -- Map folders read only if you don't need write access -- If you need any API access, make sure that you do not grant permission that aren't needed - -## Use Home Assistant User backend - -Instead of allowing users to set new login credential in plain text config, use the Home Assistant [Auth backend][hassio-api-auth]. You can enable the access to API with `auth_api: true`. Now you are able to send the login credential to auth backend and validate it again Home Assistant. - -We have some sample and helpers around that system collected in a [GitHub repository][hassio-auth]. Feel free to copy and paste it or provide your own scripts. - -[hassio-auth]: https://github.com/home-assistant/hassio-auth -[hassio-api-auth]: https://github.com/home-assistant/hassio/blob/dev/API.md#auth--sso-api diff --git a/website/versioned_docs/version-0.93.0/hassio_debugging.md b/website/versioned_docs/version-0.93.0/hassio_debugging.md deleted file mode 100644 index fff61f80..00000000 --- a/website/versioned_docs/version-0.93.0/hassio_debugging.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Debugging Hass.io -id: version-0.93.0-hassio_debugging -original_id: hassio_debugging ---- - -> This section is not for end users. End users should use the [SSH add-on] to SSH into Hass.io. This is for developers of Hass.io. Do not ask for support if you are using these options. - -[SSH add-on]: https://www.home-assistant.io/addons/ssh/ - -The following debug tips and tricks are for developers who are running the Hass.io image and are working on the base image. If you use the generic Linux installer script, you should be able to access your host and logs as per your host. - -## Debug Supervisor - -Visual Studio Code config: -```json -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Hass.io remote debug", - "type": "python", - "request": "attach", - "port": 33333, - "host": "IP", - "pathMappings": [ - { - "localRoot": "${workspaceFolder}", - "remoteRoot": "/usr/src/hassio" - } - ] - } - ] -} -``` - -You need set the dev mode on supervisor and enable debug with options. You need also install the Remote debug Add-on from Developer Repository to expose the debug port to Host. - -## SSH access to the host - -### resinOS based Hass.io (deprecated) -Create an `authorized_keys` file containing your public key, and place it in the root of the boot partition of your SD card. See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. Once the device is booted, you can access your device as root over SSH on port 22222. - -### HassOS based Hass.io -Use a USB drive formatted with FAT, ext4, or NTFS and name it CONFIG (case sensitive). Create an `authorized_keys` file (no extension) containing your public key, and place it in the root of the USB drive. See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. From the UI, navigate to the hass.io system page and choose "Import from USB". You can now access your device as root over SSH on port 22222. Alternatively, the file will be imported from the USB when the hass.io device is rebooted. - -> Make sure when you are copying the public key to the root of the USB drive that you rename the file correctly to `authorized_keys` with no `.pub` file extension. - -You should then be able to SSH into your Hass.io device. On Mac/Linux, use: - -``` -ssh root@hassio.local -p 22222 -``` - -You will initially be logged in to Hass.io CLI for HassOS where you can perform normal [CLI functions]. If you need access to the host system use the 'login' command. [Hass.io OS] is a hypervisor for Docker. See the [Hass.io Architecture] documentation for information regarding the Hass.io supervisor. The supervisor offers an API to manage the host and running the Docker containers. Home Assistant itself and all installed addon's run in separate Docker containers. - -[CLI functions]: https://www.home-assistant.io/hassio/commandline/ -[Hass.io OS]: https://github.com/home-assistant/hassos -[Hass.io Architecture]: https://developers.home-assistant.io/docs/en/architecture_hassio.html - -## Checking the logs - -```bash -# Logs from the supervisor service on the Host OS -journalctl -f -u hassos-supervisor.service - -# Hass.io supervisor logs -docker logs hassos_supervisor - -# Home Assistant logs -docker logs homeassistant -``` - -## Accessing the container bash - -```bash -docker exec -it homeassistant /bin/bash -``` - -[windows-keys]: https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-putty-on-digitalocean-droplets-windows-users - -### Generating SSH Keys - -Windows instructions for how to generate and use private/public keys with Putty are [here][windows-keys]. Instead of the droplet instructions, add the public key as per above instructions. - -Alternative instructions, for Mac, Windows and Linux can be found [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#platform-mac). - -Follow steps 1-4 under 'Generating a new SSH key' (The other sections are not applicable to Hass.io and can be ignored.) - -Step 3 in the link above, shows the path to the private key file `id_rsa` for your chosen operating system. Your public key, `id_rsa.pub`, is saved in the same folder. Next, select all text from text box "Public key for pasting into the authorized_keys file" and save it to the root of your USB drive as `authorized_keys`. diff --git a/website/versioned_docs/version-0.94.0/config_entries_config_flow_handler.md b/website/versioned_docs/version-0.94.0/config_entries_config_flow_handler.md deleted file mode 100644 index 8266bf6a..00000000 --- a/website/versioned_docs/version-0.94.0/config_entries_config_flow_handler.md +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: Integration Configuration -sidebar_label: Configuration -id: version-0.94.0-config_entries_config_flow_handler -original_id: config_entries_config_flow_handler ---- - -> This option is currently only available for built-in components. - -Integrations can be set up via the user interface by adding support for a config config to create a config entry. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like Hass.io). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -## Updating the manifest - -You need to update your integrations manifest to inform Home Assistant that your integration has a config flow. This is done by adding `config_flow: true` to your manifest ([docs](creating_integration_manifest.md#config-flow)). - -## Defining your config flow - -Config entries uses the [data flow entry framework](data_entry_flow_index.md) to define their config flows. The config flow needs to be defined in the file `config_flow.py` in your integration folder. - -To define it, extend the ConfigFlow base class from the config entries module, and decorate it with the `HANDLERS.register` decorator: - -```python -from homeassistant import config_entries - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(config_entries.ConfigFlow): -``` - -## Defining steps - -Your config flow will need to define steps of your configuration flow. The docs for [Data Entry Flow](data_entry_flow_index.md) describe the different return values of a step. Here is an example on how to define the `user` step. - -```python -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, info): - if info is not None: - # process info - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema({ - vol.Required('password'): str - }) - ) -``` - -There are a few step names reserved for system use: - -| Step name | Description | -| --------- | ----------- | -| `user` | Invoked when a user initiates a flow via the user interface. -| `zeroconf` | Invoked if your integration has been discovered via Zeroconf/mDNS as specified [using `zeroconf` in the manifest](creating_integration_manifest.md#zeroconf). -| `homekit` | Invoked if your integration has been discovered via HomeKit as specified [using `homekit` in the manifest](creating_integration_manifest.md#homekit). -| `ssdp` | Invoked if your integration has been discovered via SSDP/uPnP as specified [using `ssdp` in the manifest](creating_integration_manifest.md#ssdp). -| `discovery` | _DEPRECATED_ Invoked if your integration has been discovered by the discovery integration. - -## Discovery steps - -When an integration is discovered, their respective discovery step is invoked with the discovery information. The step will have to check the following things: - - - Make sure there are no other instances of this config flow in progress of setting up the discovered device. This can happen if there are multiple ways of discovering that a device is on the network. - - Make sure that the device is not already set up. - - Invoking a discovery step should never result in a finished flow and a config entry. Always confirm with the user. - - ## Discoverable integrations that require no authentication - -If your integration is discoverable without requiring any authentication, you'll be able to use the Discoverable Flow that is built-in. This flow offers the following features: - - - Detect if devices/services can be discovered on the network before finishing the config flow. - - Support all manifest-based discovery protocols. - - Limit to only 1 config entry. It is up to the config entry to discover all available devices. - -```python -"""Config flow for LIFX.""" -from homeassistant.helpers import config_entry_flow -from homeassistant import config_entries -from .const import DOMAIN - - -async def _async_has_devices(hass): - """Return if there are devices that can be discovered.""" - import aiolifx - - lifx_ip_addresses = await aiolifx.LifxScan(hass.loop).scan() - return len(lifx_ip_addresses) > 0 - - -config_entry_flow.register_discovery_flow( - # Domain of your integration - DOMAIN, - # Title of the created config entry - 'LIFX', - # async method that returns a boolean if devices/services are found - _async_has_devices, - # Connection class of the integration - config_entries.CONN_CLASS_LOCAL_POLL -) -``` - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` - -When the translations are merged into Home Assistant, they will be automatically uploaded to [Lokalise](https://lokalise.co/) where the translation team will help to translate them in other languages. [More info on translating Home Assistant.](internationalization_translation.md) diff --git a/website/versioned_docs/version-0.94.0/creating_component_code_review.md b/website/versioned_docs/version-0.94.0/creating_component_code_review.md deleted file mode 100644 index 56f7ad8d..00000000 --- a/website/versioned_docs/version-0.94.0/creating_component_code_review.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Checklist for creating a component -sidebar_label: Component Checklist -id: version-0.94.0-creating_component_code_review -original_id: creating_component_code_review ---- - -A checklist of things to do when you're adding a new component. - -> Not all existing code follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on components level - -### 1. Requirements - - 1. Requirements have been added to [`manifest.json`](creating_integration_manifest.md). The `REQUIREMENTS` constant is deprecated. - 2. Requirement version should be pinned: `"requirements": ['phue==0.8.1']` - 3. We no longer want requirements hosted on GitHub. Please upload to PyPi. - -### 2. Configuration - - 1. Voluptuous schema present for [configuration validation](development_validation.md) - 2. Default parameters specified in voluptuous schema, not in `setup(…)` - 3. Schema using as many generic config keys as possible from `homeassistant.const` - 4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`. - 5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation` - 6. Never depend on users adding things to `customize` to configure behavior inside your component. - -### 3. Component/platform communication - - 1. You can share data with your platforms by leveraging `hass.data[DOMAIN]`. - 2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`. - -### 4. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - - ```python - # bad - status = requests.get(url('/status')) - - # good - from phue import Bridge - bridge = Bridge(...) - status = bridge.status() - ``` - - [Tutorial on publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) - -### 5. Make your pull request as small as possible - -Keep a new integration to the minimum functionality needed for someone to get value out of the integration. This allows reviewers to sign off on smaller chunks of code one at a time, and lets us get your new integration/features in sooner. **Pull requests containing large code dumps will not be a priority for review and may be closed.** - -- Limit to a single platform -- Do not add features not needed to directly support the single platform (such as custom services) -- Do not mix clean-ups and new features in a single pull request. -- Do not solve several issues in a single pull request. -- Do not submit pull requests that depend on other work which is still unmerged. - -### 6. Event names -Prefix component event names with the domain name. For example, use `netatmo_person` instead of `person` for the `netatmo` component. - -### 7. Tests - -Strongly consider adding tests for your component to minimize future regressions. diff --git a/website/versioned_docs/version-0.94.0/creating_component_index.md b/website/versioned_docs/version-0.94.0/creating_component_index.md deleted file mode 100644 index 9142fc07..00000000 --- a/website/versioned_docs/version-0.94.0/creating_component_index.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -title: Creating a Minimal Component -sidebar_label: Minimal Component -id: version-0.94.0-creating_component_index -original_id: creating_component_index ---- - -Alright, you learned about the [manifest](creating_integration_manifest.md), so it's time to write your first code for your integration. AWESOME. Don't worry, we've tried hard to keep it as easy as possible. - -More extensive examples of integrations are available from [our example repository](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/). - -## The code - -Each component needs to have 2 basic parts: it needs to define a `DOMAIN` constant that contains the domain of the integration. The second part is that it needs to define a setup method that returns a boolean if the set up was successful. So let's take a look at how this looks: - -```python -DOMAIN = 'hello_state' - -def setup(hass, config): - hass.states.set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -And if you prefer an async component: - -```python -DOMAIN = 'hello_state' - -async def async_setup(hass, config): - hass.states.async_set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -That's it! If you load this, you will see a new state in the state machine. - -To load this, add `hello_state:` to your `configuration.yaml` file and create a file `/custom_components/hello_state/__init__.py` with one of the two codeblocks above to test it locally. diff --git a/website/versioned_docs/version-0.94.0/creating_integration_manifest.md b/website/versioned_docs/version-0.94.0/creating_integration_manifest.md deleted file mode 100644 index 66e2f681..00000000 --- a/website/versioned_docs/version-0.94.0/creating_integration_manifest.md +++ /dev/null @@ -1,139 +0,0 @@ ---- -title: Integration Manifest -sidebar_label: Manifest -id: version-0.94.0-creating_integration_manifest -original_id: creating_integration_manifest ---- - -Since 0.92.0, every integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, except for custom components. - -```json -{ - "domain": "hue", - "name": "Philips Hue", - "documentation": "https://www.home-assistant.io/components/hue", - "dependencies": ["mqtt"], - "codeowners": ["@balloob"], - "requirements": ["aiohue==1.9.1"] -} -``` - -Or a minimal example that you can copy into your project: - -```json -{ - "domain": "your_domain_name", - "name": "Your Integration", - "documentation": "https://www.example.com", - "dependencies": [], - "codeowners": [], - "requirements": [] -} -``` - -## Domain - -The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. - -## Name - -The name of the integration. - -## Documentation - -The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/` - -## Dependencies - -Dependencies are other Home Assistant integrations that you want Home Assistant to set up successfully prior to the integration being loaded. This can be necessary in case you want to offer functionality from that other integration, like using webhooks or an MQTT connection. - -## Code Owners - -GitHub usernames or team names of people that are responsible for this integration. You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included. - -## Config Flow - -Specify the `config_flow` key if your integration has a config flow to create a config entry. When specified, the file `config_flow.py` needs to exist in your integration. - -```json5 -{ - "config_flow": true -} -``` - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you are running in a virtual environment. This will make sure that all requirements are present at startup. If steps fail, like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is an array of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v3.2.0: `["pychromecast==3.2.0"]`. - -> Because of how Home Assistant installs requirements on demand, actual Python imports of your requirements should be done inside functions instead of at the root level of your Python files. - -### Custom requirements during development & testing - -During the development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using `pychromecast` as an example: - -```bash -pip install pychromecast==3.2.0 --target ~/.homeassistant/deps -hass --skip-pip -``` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is specified in `requirements`. - -If you need to make changes to a requirement to support your component, it's also possible to install a development version of the requirement using `pip install -e`: - -```bash -git clone https://github.com/balloob/pychromecast.git -pip install -e ./pychromecast -hass --skip-pip -``` - -## Zeroconf - -If your integration supports discovery via [Zeroconf](https://en.wikipedia.org/wiki/Zero-configuration_networking), you can add the type to your manifest. If the user has the `zeroconf` integration loaded, it will load the `zeroconf` step of your integration's config flow when it is discovered. - -```json5 -{ - "zeroconf": ["_googlecast._tcp.local."] -} -``` - -## SSDP - -If your integration supports discovery via [SSDP](https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol), you can add the type to your manifest. If the user has the `ssdp` integration loaded, it will load the `ssdp` step of your integration's config flow when it is discovered. We support SSDP discovery by ST, manufacturer and device type. Your integration is discovered if any of the specified info is found. It's up to your config flow to filter out duplicates. - -```json5 -{ - "ssdp": { - "st": [ - "roku:ecp" - ], - "manufacturer": [ - "Roku" - ], - "device_type": [ - "urn:roku-com:device:player:1-0" - ] - } -} -``` - -## HomeKit - -If your integration supports discovery via HomeKit, you can add the supported model names to your manifest. If the user has the `zeroconf` integration loaded, it will load the `homekit` step of your integration's config flow when it is discovered. - -HomeKit discovery works by testing if the discovered modelname starts with any of the model names specified in the manifest.json. - -```json5 -{ - "homekit": { - "models": [ - "LIFX" - ] - } -} -``` - -Discovery via HomeKit does not mean that you have to talk the HomeKit protocol to communicate with your device. You can communicate with the device however you see fit. - -When a discovery info is routed to your integration because of this entry in your manifest, the discovery info is no longer routed to integrations that listen to the HomeKit zeroconf type. diff --git a/website/versioned_docs/version-0.94.0/creating_platform_code_review.md b/website/versioned_docs/version-0.94.0/creating_platform_code_review.md deleted file mode 100644 index df0def85..00000000 --- a/website/versioned_docs/version-0.94.0/creating_platform_code_review.md +++ /dev/null @@ -1,88 +0,0 @@ ---- -title: Checklist for creating a platform -sidebar_label: Platform Checklist -id: version-0.94.0-creating_platform_code_review -original_id: creating_platform_code_review ---- - -A checklist of things to do when you're adding a new platform. - -> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them! - -### 0. Common - - 1. Follow our [Style guidelines](development_guidelines.md) - 2. Use existing constants from [`const.py`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/const.py) - * Only add new constants to `const.py` if they are widely used. Otherwise keep them on platform level - * Use `CONF_MONITORED_CONDITIONS` instead of `CONF_MONITORED_VARIABLES` - -### 1. Requirements - - 1. Requirements have been added to [`manifest.json`](creating_integration_manifest.md). The `REQUIREMENTS` constant is deprecated. - 2. Requirement version should be pinned: `"requirements": ['phue==0.8.1']` - 3. We no longer want requirements hosted on GitHub. Please upload to PyPi. - -### 2. Configuration - - 1. If the platform can be set up directly, add a voluptuous schema for [configuration validation](development_validation.md) - 2. Voluptuous schema extends schema from component
(e.g., `hue.light.PLATFORM_SCHEMA` extends `light.PLATFORM_SCHEMA`) - 3. Default parameters specified in voluptuous schema, not in `setup_platform(...)` - 4. Your `PLATFORM_SCHEMA` should use as many generic config keys as possible from `homeassistant.const` - 5. Never depend on users adding things to `customize` to configure behavior inside your platform. - -```python -import voluptuous as vol - -from homeassistant.const import CONF_FILENAME, CONF_HOST -from homeassistant.components.light import PLATFORM_SCHEMA -import homeassistant.helpers.config_validation as cv - -CONF_ALLOW_UNREACHABLE = 'allow_unreachable' -DEFAULT_UNREACHABLE = False - -PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ - vol.Required(CONF_HOST): cv.string, - vol.Optional(CONF_ALLOW_UNREACHABLE, - default=DEFAULT_UNREACHABLE): cv.boolean, - vol.Optional(CONF_FILENAME): cv.string, -}) -``` - -### 3. Setup Platform - - 1. Verify that the passed in configuration (user/pass/host etc.) works. - 2. Group your calls to `add_devices` if possible. - 3. If the platform adds extra services, the format should be `.`. So if your integration's domain is "awesome_sauce" and you are making a light platform, you would register services under the `awesome_sauce` domain. Make sure that your services [verify permissions](auth_permissions.md#checking-permissions). - -### 5. Entity - - 1. Extend the entity from the integration you're building a platform for. - - ```python - from homeassistant.components.light import Light - - class HueLight(Light): - ... - ``` - - 2. Avoid passing in `hass` as a parameter to the entity. When the entity has been added to Home Assistant, `hass` will be set on the entity when the entity is added to Home Assistant. This means you can access `hass` as `self.hass` inside the entity. - 3. Do not call `update()` in constructor, use `add_entities(devices, True)` instead. - 4. Do not do any I/O inside properties. Cache values inside `update()` instead. - 5. When dealing with time, state and/or attributes should not contain relative time since something happened. Instead, it should store UTC timestamps. - 6. Leverage the [entity lifecycle callbacks](entity_index.md#lifecycle-hooks) to attach event listeners or clean up connections. - -### 4. Communication with devices/services - - 1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API. - - ```python - # bad - status = requests.get(url('/status')) - - # good - from phue import Bridge - bridge = Bridge(...) - status = bridge.status() - ``` - - [Tutorial on publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/) diff --git a/website/versioned_docs/version-0.94.0/data_entry_flow_index.md b/website/versioned_docs/version-0.94.0/data_entry_flow_index.md deleted file mode 100644 index 670df030..00000000 --- a/website/versioned_docs/version-0.94.0/data_entry_flow_index.md +++ /dev/null @@ -1,284 +0,0 @@ ---- -title: Data Entry Flow -sidebar_label: Introduction -id: version-0.94.0-data_entry_flow_index -original_id: data_entry_flow_index ---- - -Data Entry Flow is a data entry framework that is part of Home Assistant. Data entry is done via data entry flows. A flow can represent a simple login form or a multi-step setup wizard for a component. A Flow Manager is managing all flows that are in progress and handles creation of new flows. - -Data Entry Flow is being used in Home Assistant to create config entries. - -## Flow Manager - -This is the class that manages the flows that are in progress. When instantiating one, you pass in two async callbacks: - -```python -async def async_create_flow(handler, context=context, data=data) -``` - -The manager delegates instantiating of config flow handlers to this async callback. This allows the parent of the manager to define their own way of finding handlers and preparing a handler for instantiation. For example, in the case of the config entry manager, it will make sure that the dependencies and requirements are setup. - -```python -async def async_finish_flow(flow, result) -``` - -This async callback is called when a flow is finished or aborted. i.e. `result['type'] in [RESULT_TYPE_CREATE_ENTRY, RESULT_TYPE_ABORT]`. The callback function can modify result and return it back, if the result type changed to `RESULT_TYPE_FORM`, the flow will continue running, display another form. - -If the result type is `RESULT_TYPE_FORM`, the result should like: -```python -{ - # The result type of the flow - 'type': RESULT_TYPE_FORM, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # name of the step, flow.async_step_[step_id] will be called when form submitted - 'step_id': 'init', - # a voluptuous schema to build and validate user input - 'data_schema': vol.Schema(), - # an errors dict, None if no errors - 'errors': errors, - # a detail information about the step - 'description_placeholders': description_placeholders, -} -``` - -If the result type is `RESULT_TYPE_CREATE_ENTRY`, the result should like: -```python -{ - # Data schema version of the entry - 'version': 2, - # The result type of the flow - 'type': RESULT_TYPE_CREATE_ENTRY, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # title and data as created by the handler - 'title': 'Some title', - 'result': { - 'some': 'data' - }, -} -``` - -If the result type is `RESULT_TYPE_ABORT`, the result should like: -```python -{ - # The result type of the flow - 'type': RESULT_TYPE_ABORT, - # the id of the flow - 'flow_id': 'abcdfgh1234, - # handler name - 'handler': 'hue', - # the abort reason - 'reason': 'already_configured', -} -``` - - -## Flow Handler - -Flow handlers will handle a single flow. A flow contains one or more steps. When a flow is instantiated, the `FlowHandler.init_step` step will be called. Each step has three different possible results: "Show Form", "Abort" and "Create Entry". - -At a minimum, each flow handler will have to define a version number and a step. This doens't have to be `init`, as `async_create_flow` can assign `init_step` depends on diffreent workflow, for example in configuration, `context.source` will be use as `init_step`. - -The bare minimum config flow: - -```python -from homeassistant import data_entry_flow - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - # The schema version of the entries that it creates - # Home Assistant will call your migrate method if the version changes - # (this is not implemented yet) - VERSION = 1 - - async def async_step_user(self, user_input=None): - # Do something -``` - -### Show Form - -This result type will show a form to the user to fill in. You define the current step, the schema of the data (using voluptuous) and optionally a dictionary of errors. Title and description of the step will be provided via the translation file. Where this is defined depends on the context of the data entry flow. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema) - ) -``` - -After the user has filled in the form, the step method will be called again and the user input is passed in. Your step will only be called if the user input passes your data schema. When the user passes in data, you will have to do extra validation of the data. For example, you can verify that the passed in username and password are valid. - -If something is wrong, you can return a dictionary with errors. Each key in the error dictionary refers to a field name that contains the error. Use the key `base` if you want to show an error unrelated to a specific field. The specified errors need to refer to a key in a translation file. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # See next section on create entry usage - return self.create_entry(...) - - errors['base'] = 'auth_error' - - # Use OrderedDict to guarantee order of the form shown to the user - data_schema = OrderedDict() - data_schema[vol.Required('username')] = str - data_schema[vol.Required('password')] = str - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema(data_schema), - errors=errors - ) -``` - -#### Multi-step flows - -If the user input passes validation, you can again return one of the three return values. If you want to navigate the user to the next step, return the return value of that step: - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_init(self, user_input=None): - errors = {} - if user_input is not None: - # Validate user input - valid = await is_valid(user_input) - if valid: - # Store info to use in next step - self.init_info = user_input - # Return the form of the next step - return await self.async_step_account() - - ... -``` - -### Create Entry - -When the result is "Create Entry", an entry will be created and passed to the parent of the flow manager. A success message is shown to the user and the flow is finished. You create an entry by passing a title and data. The title can be used in the UI to indicate to the user which entry it is. Data can be any data type, as long as it is JSON serializable. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - return self.create_entry( - title='Title of the entry', - data={ - 'something_special': user_input['username'] - } - ) -``` - -### Abort - -When a flow cannot be finished, you need to abort it. This will finish the flow and inform the user that the flow has finished. Reasons for a flow to not be able to finish can be that a device is already configured or not compatible with Home Assistant. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, user_input=None): - return self.async_abort( - reason='not_supported' - ) -``` - -### External Step & External Step Done - -It is possible that a user needs to finish a config flow by doing actions on an external website. For example, setting up an integration by being redirected to an external webpage. This is commonly used by integrations that use OAuth2 to authorize a user. - -_The example is about config entries, but works with other parts that use data entry flows too._ - -The flow works as follows: - - 1. User starts config flow in Home Assistant - 2. Config flow prompts user to finish the flow on an external website - 3. User opens the external website - 4. Upon completion of the external step, the user's browser will be redirected to a Home Assistant endpoint to deliver the response. - 5. The endpoint validates the response, and upon validation, marks the external step as done and returns JavaScript code to close the window: ``. - - To be able to route the result of the external step to the Home Assistant endpoint, you will need to make sure the config flow ID is included. If your external step is an OAuth2 flow, you can leverage the oauth2 state for this. This is a variable that is not interpreted by the authorization page but is passed as-is to the Home Assistant endpoint. - 6. The window closes and the Home Assistant user interface with the config flow will be visible to the user again. - 7. The config flow has automatically advanced to the next step when the external step was marked as done. The user is prompted with the next step. - -Example configuration flow that includes an external step. - -```python -from homeassistant import config_entries - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - VERSION = 1 - data = None - - async def async_step_user(self, user_input=None): - if not user_input: - return self.async_external_step( - step_id='user', - url='https://example.com/?config_flow_id={}'.format( - self.flow_id - ), - ) - - self.data = user_input - return self.async_external_step_done(next_step_id='finish') - - async def async_step_finish(self, user_input=None): - return self.async_create_entry( - title=self.data['title'], - data=self.data - ) -``` - -Example code to mark an external step as done: - -```python -from homeassistant import data_entry_flow - -async def handle_result(hass, flow_id, data): - result = await hass.config_entries.async_configure(flow_id, data) - - if result['type'] == data_entry_flow.RESULT_TYPE_EXTERNAL_STEP_DONE: - return "success!" - else: - return "Invalid config flow specified" -``` - -## Translations - -Data entry flows depend on translations for showing the text in the forms. It depends on the parent of a data entry flow manager where this is stored. - -## Initializing a config flow from an external source - -You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing a flow: - -```python -await flow_mgr.async_init('hue', context={'source': data_entry_flow.SOURCE_DISCOVERY}, data=discovery_info) -``` - -The config flow handler will not start with the `init` step. Instead, it will be instantiated with a step name equal to the source. The step should follow the same return values as a normal step. - -```python -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_discovery(self, info): - # Handle discovery info -``` diff --git a/website/versioned_docs/version-0.94.0/device_registry_index.md b/website/versioned_docs/version-0.94.0/device_registry_index.md deleted file mode 100644 index b77175ba..00000000 --- a/website/versioned_docs/version-0.94.0/device_registry_index.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Device Registry -sidebar_label: Introduction -id: version-0.94.0-device_registry_index -original_id: device_registry_index ---- - -The device registry is a registry where Home Assistant keeps track of devices. A device is represented in Home Assistant via one or more entities. For example, a battery-powered temperature and a humidity sensor might expose entities for temperature, humidity and battery level. - -Device registry overview - -## What is a device? - -A device in Home Assistant represents a physical device that has its own control unit. The control unit itself does not have to be smart, but it should be in control of what happens. For example, an Ecobee thermostat with 4 room sensors equals 5 devices in Home Assistant, one for the thermostat including all sensors inside it, and one for each sensor. Each device exists in a specific geographical area, and may have more than one input or output within that area. - -If you connect a sensor to another device to read some of its data, it should still be represented as two different devices. The reason for this is that the sensor could be moved to read the data of another device. - -A device that offers multiple endpoints, where parts of the device sense or output in different areas, should be split into separate devices and refer back to parent device with the `via_device` attribute. This allows the separate endpoints to be assigned to different areas in the building. - -> Although not currently available, we could consider offering an option to users to merge devices. - -## Device properties - -| Attribute | Description | -| --------- | ----------- | -| id | Unique ID of device (generated by Home Assistant) -| name | Name of this device -| connections | A set of tuples of `(connection_type, connection identifier)`. Connection types are defined in the device registry module. -| identifiers | Set of identifiers. They identify the device in the outside world. An example is a serial number. -| manufacturer | The manufacturer of the device. -| model | The model of the device. -| config_entries | Config entries that are linked to this device. -| sw_version | The firmware version of the device. -| via_device | Identifier of a device that routes messages between this device and Home Assistant. Examples of such devices are hubs, or parent devices of a sub-device. This is used to show device topology in Home Assistant. -| area_id | The Area which the device is placed in. - -## Defining devices - -> Entity device info is only read if the entity is loaded via a [config entry](config_entries_index.md). - -Each entity is able to define a device via the `device_info` property. This property is read when an entity is added to Home Assistant via a config entry. A device will be matched up with an existing device via supplied identifiers and connections, like serial numbers or MAC addresses. - -```python -# Inside a platform -class HueLight(LightEntity): - - @property - def device_info(self): - return { - 'identifiers': { - # Serial numbers are unique identifiers within a specific domain - (hue.DOMAIN, self.unique_id) - }, - 'name': self.name, - 'manufacturer': self.light.manufacturername, - 'model': self.light.productname, - 'sw_version': self.light.swversion, - 'via_device': (hue.DOMAIN, self.api.bridgeid), - } - -``` - -Components are also able to register devices in the case that there are no entities representing them. An example is a hub that communicates with the lights. - -```python -# Inside a component -from homeassistant.helpers import device_registry as dr - -device_registry = await dr.async_get_registry(hass) - -device_registry.async_get_or_create( - config_entry=entry.entry_id, - connections={ - (dr.CONNECTION_NETWORK_MAC, config.mac) - }, - identifiers={ - (DOMAIN, config.bridgeid) - }, - manufacturer='Signify', - name=config.name, - model=config.modelid, - sw_version=config.swversion, -) -``` diff --git a/website/versioned_docs/version-0.94.0/entity_cover.md b/website/versioned_docs/version-0.94.0/entity_cover.md deleted file mode 100644 index b934674a..00000000 --- a/website/versioned_docs/version-0.94.0/entity_cover.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -title: Cover Entity -sidebar_label: Cover -id: version-0.94.0-entity_cover -original_id: entity_cover ---- - -A cover entity is a device that controls an opening or cover, such as a garage door and window shade. Derive entity platforms from [`homeassistant.components.cover.CoverDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/cover/__init__.py). - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -### Platform Properties (to be implemented by deriving platform classes) - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| current_cover_position | int | None | The current position of cover where 0 means closed and 100 is fully open. Required with `SUPPORT_SET_POSITION`. -| current_cover_tilt_position | int | None | The current tilt position of the cover where 0 means closed/no tilt and 100 means open/maximum tilt. Required with `SUPPORT_SET_TILT_POSITION` -| is_opening | bool | None | If the cover is opening or not. Used to determine `state`. -| is_closing | bool | None | If the cover is closing or not. Used to determine `state`. -| is_closed | bool | `NotImplementedError()` | If the cover is closed or not. if the state is unknown, return `None`. Used to determine `state`. - -### Entity Properties (base class properties which may be overriden) - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| device_class | string | None | Describes the type/class of the cover. Must be `None` or one of the valid values from the table below. -| supported_features | int (bitwise) | Value determined from `current_cover_position` and `current_cover_tilt_position` | Describes the supported features. See the related table below for details. - -### Device Classes -| Constant | Description -|----------|-----------------------| -| `DEVICE_CLASS_AWNING` | Control of an awning, such as an exterior retractible window, door, or patio cover. -| `DEVICE_CLASS_BLIND` | Control of blinds, which are linked slats that expand or collapse to cover an opening or may be tilted to partially cover an opening, such as window blinds. -| `DEVICE_CLASS_CURTAIN` | Control of curtains or drapes, which is often fabric hung above a window or door that can be drawn open. -| `DEVICE_CLASS_DAMPER` | Control of a mechanical damper that reduces air flow, sound, or light. -| `DEVICE_CLASS_DOOR` | Control of a door or gate that provides access to an area. -| `DEVICE_CLASS_GARAGE` | Control of a garage door that provides access to a garage. -| `DEVICE_CLASS_SHADE` | Control of shades, which are a continous plane of material or connected cells that expanded or collapsed over an opening, such as window shades. -| `DEVICE_CLASS_SHUTTER` | Control of shutters, which are linked slats that swing out/in to cover an opening or may be tilted to partially cover an opening, such as indoor or exterior window shutters. -| `DEVICE_CLASS_WINDOW` | Control of a physical window that opens and closes or may tilt. - -### States -| Constant | Description -|----------|------------------------| -| `STATE_OPENING` | The cover is in the process of opening to reach a set position. -| `STATE_OPEN` | The cover has reached the open position. -| `STATE_CLOSING` | The cover is in the process of closing to reach a set position. -| `STATE_CLOSED` | The cover has reach the closed position. - - -### Supported Features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Constant | Description | -|----------|--------------------------------------| -| `SUPPORT_OPEN` | The cover supports being opened. -| `SUPPORT_CLOSE` | The cover supports being closed. -| `SUPPORT_SET_POSITION` | The cover supports moving to a specific position between opened and closed. -| `SUPPORT_STOP` | The cover supports stopping the current action (open, close, set position) -| `SUPPORT_OPEN_TILT` | The cover supports being tilting open. -| `SUPPORT_CLOSE_TILT` | The cover supports being tilting closed. -| `SUPPORT_SET_TILT_POSITION` | The cover supports moving to a specific tilt position between opened and closed. -| `SUPPORT_STOP_TILT` | The cover supports stopping the current tilt action (open, close, set position) - -## Methods - -### Open cover - -Only implement this method if the flag `SUPPORT_OPEN` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover(self, **kwargs): - """Open the cover.""" - - async def async_open_cover(self, **kwargs): - """Open the cover.""" -``` - -### Close cover - -Only implement this method if the flag `SUPPORT_CLOSE` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover(self, **kwargs): - """Close cover.""" - - async def async_close_cover(self, **kwargs): - """Close cover.""" -``` - -### Set cover position - -Only implement this method if the flag `SUPPORT_SET_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" - - async def async_set_cover_position(self, **kwargs): - """Move the cover to a specific position.""" - -``` - -### Stop cover - -Only implement this metohd if the flag `SUPPORT_STOP` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover(self, **kwargs): - """Stop the cover.""" -``` - -### Open cover tilt - -Only implement this method if the flag `SUPPORT_OPEN_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" - - async def async_open_cover_tilt(self, **kwargs): - """Open the cover tilt.""" -``` - -### Close cover tilt - -Only implement this method if the flag `SUPPORT_CLOSE_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" - - async def async_close_cover_tilt(self, **kwargs): - """Close the cover tilt.""" -``` - -### Set cover tilt position - -Only implement this method if the flag `SUPPORT_SET_TILT_POSITION` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" - - async def async_set_cover_tilt_position(self, **kwargs): - """Move the cover tilt to a specific position.""" -``` - -### Stop cover tilt - -Only implement this method if the flag `SUPPORT_STOP_TILT` is set. - -```python -class MyCover(CoverDevice): - # Implement one of these methods. - - def stop_cover_tilt(self, **kwargs): - """Stop the cover.""" - - async def async_stop_cover_tilt(self, **kwargs): - """Stop the cover.""" -``` diff --git a/website/versioned_docs/version-0.94.0/external_api_rest.md b/website/versioned_docs/version-0.94.0/external_api_rest.md deleted file mode 100644 index d53f4b02..00000000 --- a/website/versioned_docs/version-0.94.0/external_api_rest.md +++ /dev/null @@ -1,552 +0,0 @@ ---- -title: REST API -id: version-0.94.0-external_api_rest -original_id: external_api_rest ---- - -Home Assistant provides a RESTful API on the same port as the web frontend. (default port is port 8123). - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file. - -* http://IP_ADDRESS:8123/ is an interface to control Home Assistant. -* http://IP_ADDRESS:8123/api/ is a RESTful API. - -The API accepts and returns only JSON encoded objects. - -All API calls have to be accompanied by the header `Authorization: Bearer ABCDEFGH`, where `ABCDEFGH` is replaced by your token. You can obtain a token ("Long-Lived Access Token") by logging into the frontend using a web browser, and going to [your profile](https://www.home-assistant.io/docs/authentication/#your-account-profile) `http://IP_ADDRESS:8123/profile`. - -There are multiple ways to consume the Home Assistant Rest API. One is with `curl`: - -```bash -$ curl -X GET \ - -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://IP_ADDRESS:8123/ENDPOINT -``` - -Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. - -```python -from requests import get - -url = 'http://localhost:8123/ENDPOINT' -headers = { - 'Authorization': 'Bearer ABCDEFGH', - 'content-type': 'application/json', -} - -response = get(url, headers=headers) -print(response.text) -``` -Another option is to use the Restful Command component https://www.home-assistant.io/components/rest_command/ in a Home Assistant automation or script. - -```yaml -turn_light_on: - url: http://localhost:8123/api/states/light.study_light - method: POST - headers: - authorization: 'Bearer ABCDEFGH' - content-type: 'application/json' - payload: '{"state":"on"}' -``` - -Successful calls will return status code 200 or 201. Other status codes that can return are: - -- 400 (Bad Request) -- 401 (Unauthorized) -- 404 (Not Found) -- 405 (Method not allowed) - -### Actions - -The API supports the following actions: - -#### GET /api/ - -Returns a message if the API is up and running. - -```json -{ - "message": "API running." -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/ -``` - -#### GET /api/config - -Returns the current configuration as JSON. - -```json -{ - "components":[ - "sensor.cpuspeed", - "frontend", - "config.core", - "http", - "map", - "api", - "sun", - "config", - "discovery", - "conversation", - "recorder", - "group", - "sensor", - "websocket_api", - "automation", - "config.automation", - "config.customize" - ], - "config_dir":"/home/ha/.homeassistant", - "elevation":510, - "latitude":45.8781529, - "location_name":"Home", - "longitude":8.458853651, - "time_zone":"Europe/Zurich", - "unit_system":{ - "length":"km", - "mass":"g", - "temperature":"\u00b0C", - "volume":"L" - }, - "version":"0.56.2", - "whitelist_external_dirs":[ - "/home/ha/.homeassistant/www", - "/home/ha/.homeassistant/" - ] -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/config -``` - -#### GET /api/discovery_info - -Returns basic information about the Home Assistant instance as JSON. - -```json -{ - "base_url": "http://192.168.0.2:8123", - "location_name": "Home", - "requires_api_password": true, - "version": "0.56.2" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/discovery_info -``` - -#### GET /api/events - -Returns an array of event objects. Each event object contains event name and listener count. - -```json -[ - { - "event": "state_changed", - "listener_count": 5 - }, - { - "event": "time_changed", - "listener_count": 2 - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/events -``` - -#### GET /api/services - -Returns an array of service objects. Each object contains the domain and which services it contains. - -```json -[ - { - "domain": "browser", - "services": [ - "browse_url" - ] - }, - { - "domain": "keyboard", - "services": [ - "volume_up", - "volume_down" - ] - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/services -``` - -#### GET /api/history/period/<timestamp> - -Returns an array of state changes in the past. Each object contains further details for the entities. - -The `` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period. - -You can pass the following optional GET parameters: - -- `filter_entity_id=` to filter on one or more entities - comma separated. -- `end_time=` to choose the end of the period in URL encoded format (defaults to 1 day). - -```json -[ - [ - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-3.9" - }, - { - "attributes": { - "friendly_name": "Weather Temperature", - "unit_of_measurement": "\u00b0C" - }, - "entity_id": "sensor.weather_temperature", - "last_changed": "2016-02-06T22:15:00+00:00", - "last_updated": "2016-02-06T22:15:00+00:00", - "state": "-1.9" - }, - ] -] -``` - -Sample `curl` commands: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00 -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature -``` - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00 -``` - -#### GET /api/states - -Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" http://localhost:8123/api/states -``` - -#### GET /api/states/<entity_id> - -Returns a state object for specified entity_id. Returns 404 if not found. - -```json -{ - "attributes":{ - "azimuth":336.34, - "elevation":-17.67, - "friendly_name":"Sun", - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id":"sun.sun", - "last_changed":"2016-05-30T21:43:29.204838+00:00", - "last_updated":"2016-05-30T21:50:30.529465+00:00", - "state":"below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### GET /api/error_log - -Retrieve all errors logged during the current session of Home Assistant as a plaintext response. - -```text -15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions -15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml -15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent -``` - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/error_log -``` - -#### GET /api/camera_proxy/camera.<entity_id> - -Returns the data (image) from the specified camera entity_id. - -Sample `curl` command: - -```bash -$ curl -X GET -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg -``` - -#### POST /api/states/<entity_id> - -Updates or creates the current state of an entity. - -Expects a JSON object that has at least a state attribute: - -```json -{ - "state": "below_horizon", - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - } -} -``` - -The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object. - -```json -{ - "attributes": { - "next_rising":"2016-05-31T03:39:14+00:00", - "next_setting":"2016-05-31T19:16:42+00:00" - }, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:29.204838+00:00", - "last_updated": "2016-05-30T21:47:30.533530+00:00", - "state": "below_horizon" -} -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \ - http://localhost:8123/api/states/sensor.kitchen_temperature -``` - -#### POST /api/events/<event_type> - -Fires an event with event_type - -You can pass an optional JSON object to be used as `event_data`. - -```json -{ - "next_rising":"2016-05-31T03:39:14+00:00", -} -``` - -Returns a message if successful. - -```json -{ - "message": "Event download_file fired." -} -``` - -#### POST /api/services/<domain>/<service> - -Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first. - -You can pass an optional JSON object to be used as `service_data`. - -```json -{ - "entity_id": "light.Ceiling" -} -``` - -Returns a list of states that have changed while the service was being executed. - -```json -[ - { - "attributes": {}, - "entity_id": "sun.sun", - "last_changed": "2016-05-30T21:43:32.418320+00:00", - "state": "below_horizon" - }, - { - "attributes": {}, - "entity_id": "process.Dropbox", - "last_changed": "22016-05-30T21:43:32.418320+00:00", - "state": "on" - } -] -``` - -Sample `curl` commands: - -Turn the light on: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"entity_id": "switch.christmas_lights"}' \ - http://localhost:8123/api/services/switch/turn_on -``` - -Send a MQTT message: - -```bash -$ curl -X POST \ - -H "Content-Type: application/json" \ - -H "x-ha-access:YOUR_PASSWORD" \ - -d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \ - http://localhost:8123/api/services/mqtt/publish -``` - -> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system. - -#### POST /api/template - -Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/) - -```json -{ - "template": "Paulus is at {{ states('device_tracker.paulus') }}!" -} -``` - -Returns the rendered template in plain text. - -```text -Paulus is at work! -``` - -Sample `curl` command: - -```bash -$ curl -X POST -H "Authorization: Bearer ABCDEFGH" \ - -H "Content-Type: application/json" \ - -d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template -``` - -#### POST /api/config/core/check_config - -Trigger a check of `configuration.yaml`. No additional data needs to be passed in with this request. - -If the check is successful, the following will be returned: - -```javascript -{ - "errors": null, - "result": "valid" -} -``` - -If the check fails, the errors attribute in the object will list what caused the check to fail. For example: - -```javascript -{ - "errors": "Integration not found: frontend:", - "result": "invalid" -} -``` - -#### POST /api/event_forwarding - -Set up event forwarding to another Home Assistant instance. - -Requires a JSON object that represents the API to forward to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was set up successfully. - -```json -{ - "message": "Event forwarding setup." -} -``` - -#### DELETE /api/event_forwarding - -Cancel event forwarding to another Home Assistant instance.
- -Requires a JSON object that represents the API to cancel forwarding to. - -```javascript -{ - "host": "machine", - "api_password": "my_super_secret_password", - "port": 8880 // optional -} -``` - -It will return a message if event forwarding was canceled successfully. - -```json -{ - "message": "Event forwarding cancelled." -} -``` diff --git a/website/versioned_docs/version-0.94.0/frontend_creating_custom_panels.md b/website/versioned_docs/version-0.94.0/frontend_creating_custom_panels.md deleted file mode 100644 index dc7c8687..00000000 --- a/website/versioned_docs/version-0.94.0/frontend_creating_custom_panels.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -title: Creating custom panels -id: version-0.94.0-frontend_creating_custom_panels -original_id: frontend_creating_custom_panels ---- - -Panels are pages that show information within Home Assistant and can allow controlling it. Panels are linked from the sidebar and rendered full screen. They have real-time access to the Home Assistant object via JavaScript. Examples of panels in the app are Map, Logbook and History. - -Besides components registering panels, users can also register panels using the `panel_custom` component. This allows users to quickly build their own custom interfaces for Home Assistant. - -## Introduction - -Panels are defined as custom elements. You can use any framework that you want, as long as you wrap it up as a custom element. To quickly get started with a panel, we've created a [React custom panel starter kit](https://github.com/home-assistant/custom-panel-starter-kit-react). - -## API reference - -The Home Assistant frontend will pass information to your panel by setting properties on your custom element. The following properties are set: - -| Property | Type | Description -| -------- | ---- | ----------- -| hass | object | Current state of Home Assistant -| narrow | boolean | if the panel should render in narrow mode -| panel | object | Panel information. Config is available as `panel.config`. - -## JavaScript versions - -The Home Assistant user interface is currently served to browsers in modern JavaScript and older JavaScript (ES5). The older version has a wider browser support but that comes at a cost of size and performance. - -If you do need to run with ES5 support, you will need to load the ES5 custom elements adapter before defining your element: - -```js -window.loadES5Adapter().then(function() { - customElements.define('my-panel', MyCustomPanel) -}); -``` diff --git a/website/versioned_docs/version-0.94.0/frontend_creating_custom_ui.md b/website/versioned_docs/version-0.94.0/frontend_creating_custom_ui.md deleted file mode 100644 index 81e62897..00000000 --- a/website/versioned_docs/version-0.94.0/frontend_creating_custom_ui.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Creating custom UI -id: version-0.94.0-frontend_creating_custom_ui -original_id: frontend_creating_custom_ui ---- - -> This feature has been derepcated and is no longer supported. To add custom UI to Home Assistant, build a [custom Lovelace card](lovelace_custom_card.md) instead. - -### State card - -If you would like to use your own [State card](frontend_add_card.md) without merging your code into [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer/) you can create your own implementation. - -Put the element source file and its dependencies in `www/custom_ui/` directory under your Home Assistant [configuration](https://www.home-assistant.io/docs/configuration/) directory. - -For example if creating a state card for the `light` domain named `state-card-my-custom-light` put `state-card-my-custom-light.html` in `www/custom_ui/`. - -That file should implement `` tag with Polymer. - -In `state-card-my-custom-light.html` you should use `` to import all the dependencies **not** used by Home Assistant's UI. -Do not import any dependencies used by the Home Assistant UI. -Importing those will work in `development: 1` mode, but will fail in production mode. - -1. In the `customize:` section of the `configuration.yaml` file put `custom_ui_state_card: state-card-my-custom-light`. -2. In the `frontend` section use `extra_html_url` to specify the URL to load. - -Example: - -`configuration.yaml`: - -```yaml -homeassistant: - customize: - light.bedroom: - custom_ui_state_card: state-card-my-custom-light - -frontend: - extra_html_url: - - /local/custom_ui/state-card-my-custom-light.html -``` - -`www/custom_ui/state-card-my-custom-light.html`: - -```html - - - - - - -``` - -> Some browsers don't support latest ECMAScript standards, these require a separate ES5 compatible file (`extra_html_url_es5`). - -For more possibilities, see the [Custom UI section](https://www.home-assistant.io/cookbook/#user-interface) on our Examples page. - -### More info dialog - -_Introduced in Home Assistant 0.69._ - -Similar to the custom State card, if you would like to use your own [More info dialog](frontend_add_more_info.md) you can create your own implementation. - -Following a similar example, if creating a more info dialog a light named `more-info-my-custom-light` put `more-info-my-custom-light.html` in `www/custom_ui/`. - -1. In the `customize:` section of the `configuration.yaml` file put `custom_ui_more_info: more-info-my-custom-light`. -2. In the `frontend` section use `extra_html_url` to specify the URL to load. - -Example: - -`configuration.yaml`: - -```yaml -homeassistant: - customize: - light.bedroom: - custom_ui_more_info: more-info-my-custom-light - -frontend: - extra_html_url: - - /local/custom_ui/more-info-my-custom-light.html -``` diff --git a/website/versioned_docs/version-0.94.0/frontend_external_bus.md b/website/versioned_docs/version-0.94.0/frontend_external_bus.md deleted file mode 100644 index c3497053..00000000 --- a/website/versioned_docs/version-0.94.0/frontend_external_bus.md +++ /dev/null @@ -1,159 +0,0 @@ ---- -title: External Bus -id: version-0.94.0-frontend_external_bus -original_id: frontend_external_bus ---- - -The frontend is able to set up a message bus with an external app that is embedding the Home Assistant frontend. This system is a generalization of the [external auth](frontend_external_auth.md), making it easier to add more commands in the future without extensive plumbing on either the app or frontend side. - -## Message exchange - -Just like external auth, message exchange is achieved by the external app making a JavaScript method available. - -Messages are passed to the external app as serialized JSON objects. The function that will be called takes a single parameter: a string. The external app will have to process the message and deal with it accordingly (or ignore it). - -On Android, your app needs to define the following method: - -```ts -window.externalApp.externalBus(message: string) -``` - -On iOS, your app needs to define the following method: - -```ts -window.webkit.messageHandlers.externalBus.postMessage(message: string); -``` - -To send messages to the frontend, serialize your message to JSON and call the following function from the external app: - -```ts -window.externalBus(message: string) -``` - -## Message format - -The message describes an action or a piece of information that the sender wants the receiver to do or know about. If it's an action, the sender will expect a response with the result of that action. A response to a command can either be successful or failed. - -### Action and Info Message format - -The format of a message that contains or provides information is the same. It contains an identifier, a type and an optional payload (depending on the type). - -A result message will re-use the identifier in the response, to indicate to which action the response is related. - -The basic format of a message is the following: - -```ts -{ - id: number; - type: string; - payload?: unknown; -} -``` - -An example message: - -```json -{ - "id": 5, - "type": "config/get" -} -``` - -### Result Message Format - -If the message was an action, the sender will expect a response with the result. The response is either success or failure. - -The type of result depends on the type of the message that it is responding to. For example, if it is responding to `config/get`, the result should be an object describing the configuration. - -Message formats: - -```ts -interface SuccessResult { - id: number; - type: "result"; - success: true; - result: unknown; -} - -interface ErrorResult { - id: number; - type: "result"; - success: false; - error: { - code: string; - message: string; - }; -} -``` - -## Supported messages - -### Get External Config - -Available in: Home Assistant 0.92 -Type: `config/get` -Direction: frontend to external app. -Expects answer: yes - -Query the external app for the external configuration. The external configuration is used to customize the experience in the frontend. - -Expected response payload: - -```ts -{ - hasSettingsScreen: boolean; -} -``` - -- `hasSettingsScreen` set to true if the external app will show a configuration screen when it receives the command `config_screen/show`. If so, a new option will be added to the sidebar to trigger the configuration screen. - -### Show Config Screen `config_screen/show` - -Available in: Home Assistant 0.92 -Type: `config_screen/show` -Direction: frontend to external app. -Expect answer: no - -Show the configuration screen of the external app. - -### Connection Status update `connection-status` - -Available in: Home Assistant 0.92 -Type: `connection-status` -Direction: frontend to external app. -Expect answer: no - -Notify the external app if the frontend is connected to Home Assistant. - -Payload structure: - -```ts -{ - event: "connected" | "auth-invalid" | "disconnected"; -} -``` - -### Trigger Haptic `haptic` - -Available in: Home Assistant 0.92 -Type: `haptic` -Direction: frontend to external app. -Expect answer: no - -Notify the external app to trigger haptic feedback. - -Payload structure: - -```ts -{ - hapticType: - | "success" - | "warning" - | "failure" - | "light" - | "medium" - | "heavy" - | "selection"; - -} -``` diff --git a/website/versioned_docs/version-0.94.0/hassio_addon_communication.md b/website/versioned_docs/version-0.94.0/hassio_addon_communication.md deleted file mode 100644 index 708d4db1..00000000 --- a/website/versioned_docs/version-0.94.0/hassio_addon_communication.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -title: Add-On Communication -id: version-0.94.0-hassio_addon_communication -original_id: hassio_addon_communication ---- - -There are different ways for communication between add-ons inside Hass.io. - -## Network - -We use an internal network that's allowed to communicate with every add-on, including to/from Home Assistant, by using its name or alias. Only add-ons that run on the host network are limited in that they can talk with all internal add-ons by their name, but all other add-ons can't address these add-ons by name. However, using an alias works for both! - -Names/aliases are used for communication inside Hass.io. -The name is generated using the following format: `{REPO}_{SLUG}`, e.g., `local_xy` or `3283fh_myaddon`. In this example, `{SLUG}` is defined in an add-on's `config.json` file. You can use this name as the DNS name also, but you need replace any `_` with `-` to have a valid hostname. If an add-on is installed locally, `{REPO}` will be `local`. If the add-on is installed from a Github repository, `{REPO}` is a hashed identifier generated from the GitHub repository's URL (ex: https://github.com/xy/my_hassio_addons). See [here](https://github.com/home-assistant/hassio/blob/587047f9d648b8491dc8eef17dc6777f81938bfd/hassio/addons/utils.py#L17) to understand how this identifier is generated. Note that this identifier is required in certain service calls that use the [Hass.io add-on API][hassio-addon-api]. You can view the repository identifiers for all currently-installed add-ons via a GET request to the hassio API `addons` endpoint. - -Use `hassio` for communication with the internal API. - -## Home Assistant - -An add-on can talk to the [Home Assistant API][hass-api] using the internal proxy. This makes it very easy to communicate with the API without knowing the password, port or any other information about the Home Assistant instance. Using this URL: `http://hassio/homeassistant/api` ensures that internal communication is redirected to the right place. The next step is to add `homeassistant_api: true` to the `config.json` file and read the environment variable `HASSIO_TOKEN`. Use this as the Home-Assistant password. - -There is also a proxy for the [Home Assistant Websocket API][hass-websocket] that works like the API proxy above and requires `HASSIO_TOKEN` as the password. Use this URL: `http://hassio/homeassistant/websocket`. - -It is also possible to talk directly to the Home Assistant instance, which is named `homeassistant`, over the internal network. However, you'll need to know the configuration that is used by the running instance. - -We have several services for Hass.io inside Home Assistant to run tasks. Send data over STDIN to an add-on to use the `hassio.addon_stdin` service. - -## Hass.io API - -To enable calls to the [Hass.io API][hassio-api], add `hassio_api: true` to the `config.json` file and read the environment variable `HASSIO_TOKEN`. Now you can use the API over the URL: `http://hassio/`. Use the `HASSIO_TOKEN` with header `X-HASSIO-KEY`. You may also need to change the Hass.io API role to `hassio_role: default`. - -Add-ons can call some API commands without needing to set `hassio_api: true`: -- `/homeassistant/api` -- `/homeassistant/api/stream` -- `/homeassistant/websocket` -- `/addons/self/*` -- `/services*` -- `/discovery*` -- `/info` - -***Note:*** For Home Assistant API access requirements, see above. - -[hass-api]: https://www.home-assistant.io/developers/rest_api/ -[hass-websocket]: https://www.home-assistant.io/developers/websocket_api/ -[hassio-api]: https://github.com/home-assistant/hassio/blob/master/API.md -[hassio-addon-api]: https://github.com/home-assistant/hassio/blob/dev/API.md#restful-for-api-addons diff --git a/website/versioned_docs/version-0.94.0/hassio_debugging.md b/website/versioned_docs/version-0.94.0/hassio_debugging.md deleted file mode 100644 index 0444593e..00000000 --- a/website/versioned_docs/version-0.94.0/hassio_debugging.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -title: Debugging Hass.io -id: version-0.94.0-hassio_debugging -original_id: hassio_debugging ---- - -> This section is not for end users. End users should use the [SSH add-on] to SSH into Hass.io. This is for developers of Hass.io. Do not ask for support if you are using these options. - -[SSH add-on]: https://www.home-assistant.io/addons/ssh/ - -The following debug tips and tricks are for developers who are running the Hass.io image and are working on the base image. If you use the generic Linux installer script, you should be able to access your host and logs as per your host. - -## Debug Supervisor - -Visual Studio Code config: -```json -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Hass.io remote debug", - "type": "python", - "request": "attach", - "port": 33333, - "host": "IP", - "pathMappings": [ - { - "localRoot": "${workspaceFolder}", - "remoteRoot": "/usr/src/hassio" - } - ] - } - ] -} -``` - -You need set the dev mode on supervisor and enable debug with options. You need also install the Remote debug Add-on from Developer Repository to expose the debug port to Host. - -## SSH access to the host - -### resinOS based Hass.io (deprecated) -Create an `authorized_keys` file containing your public key, and place it in the root of the boot partition of your SD card. See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. Once the device is booted, you can access your device as root over SSH on port 22222. - -### HassOS based Hass.io -Use a USB drive formatted with FAT, ext4, or NTFS and name it CONFIG (case sensitive). Create an `authorized_keys` file (no extension) containing your public key, and place it in the root of the USB drive. File needs to be ANSI encoded (not UTF-8) and must have Unix line ends (LF), not Windows (CR LF). See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. From the UI, navigate to the hass.io system page and choose "Import from USB". You can now access your device as root over SSH on port 22222. Alternatively, the file will be imported from the USB when the hass.io device is rebooted. - -> Make sure when you are copying the public key to the root of the USB drive that you rename the file correctly to `authorized_keys` with no `.pub` file extension. - -You should then be able to SSH into your Hass.io device. On Mac/Linux, use: - -``` -ssh root@hassio.local -p 22222 -``` - -You will initially be logged in to Hass.io CLI for HassOS where you can perform normal [CLI functions]. If you need access to the host system use the 'login' command. [Hass.io OS] is a hypervisor for Docker. See the [Hass.io Architecture] documentation for information regarding the Hass.io supervisor. The supervisor offers an API to manage the host and running the Docker containers. Home Assistant itself and all installed addon's run in separate Docker containers. - -[CLI functions]: https://www.home-assistant.io/hassio/commandline/ -[Hass.io OS]: https://github.com/home-assistant/hassos -[Hass.io Architecture]: https://developers.home-assistant.io/docs/en/architecture_hassio.html - -## Checking the logs - -```bash -# Logs from the supervisor service on the Host OS -journalctl -f -u hassos-supervisor.service - -# Hass.io supervisor logs -docker logs hassos_supervisor - -# Home Assistant logs -docker logs homeassistant -``` - -## Accessing the container bash - -```bash -docker exec -it homeassistant /bin/bash -``` - -[windows-keys]: https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-putty-on-digitalocean-droplets-windows-users - -### Generating SSH Keys - -Windows instructions for how to generate and use private/public keys with Putty are [here][windows-keys]. Instead of the droplet instructions, add the public key as per above instructions. - -Alternative instructions, for Mac, Windows and Linux can be found [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#platform-mac). - -Follow steps 1-4 under 'Generating a new SSH key' (The other sections are not applicable to Hass.io and can be ignored.) - -Step 3 in the link above, shows the path to the private key file `id_rsa` for your chosen operating system. Your public key, `id_rsa.pub`, is saved in the same folder. Next, select all text from text box "Public key for pasting into the authorized_keys file" and save it to the root of your USB drive as `authorized_keys`. diff --git a/website/versioned_docs/version-0.95.0/config_entries_config_flow_handler.md b/website/versioned_docs/version-0.95.0/config_entries_config_flow_handler.md deleted file mode 100644 index b554f2de..00000000 --- a/website/versioned_docs/version-0.95.0/config_entries_config_flow_handler.md +++ /dev/null @@ -1,143 +0,0 @@ ---- -title: Integration Configuration -sidebar_label: Configuration -id: version-0.95.0-config_entries_config_flow_handler -original_id: config_entries_config_flow_handler ---- - -> This option is currently only available for built-in components. - -Integrations can be set up via the user interface by adding support for a config config to create a config entry. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like Hass.io). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -## Updating the manifest - -You need to update your integrations manifest to inform Home Assistant that your integration has a config flow. This is done by adding `config_flow: true` to your manifest ([docs](creating_integration_manifest.md#config-flow)). - -## Defining your config flow - -Config entries uses the [data flow entry framework](data_entry_flow_index.md) to define their config flows. The config flow needs to be defined in the file `config_flow.py` in your integration folder. - -To define it, extend the ConfigFlow base class from the config entries module, and decorate it with the `HANDLERS.register` decorator: - -```python -from homeassistant import config_entries - -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(config_entries.ConfigFlow): -``` - -## Defining steps - -Your config flow will need to define steps of your configuration flow. The docs for [Data Entry Flow](data_entry_flow_index.md) describe the different return values of a step. Here is an example on how to define the `user` step. - -```python -@config_entries.HANDLERS.register(DOMAIN) -class ExampleConfigFlow(data_entry_flow.FlowHandler): - - async def async_step_user(self, info): - if info is not None: - # process info - - return self.async_show_form( - step_id='init', - data_schema=vol.Schema({ - vol.Required('password'): str - }) - ) -``` - -There are a few step names reserved for system use: - -| Step name | Description | -| --------- | ----------- | -| `user` | Invoked when a user initiates a flow via the user interface. -| `zeroconf` | Invoked if your integration has been discovered via Zeroconf/mDNS as specified [using `zeroconf` in the manifest](creating_integration_manifest.md#zeroconf). -| `homekit` | Invoked if your integration has been discovered via HomeKit as specified [using `homekit` in the manifest](creating_integration_manifest.md#homekit). -| `ssdp` | Invoked if your integration has been discovered via SSDP/uPnP as specified [using `ssdp` in the manifest](creating_integration_manifest.md#ssdp). -| `discovery` | _DEPRECATED_ Invoked if your integration has been discovered by the discovery integration. - -## Discovery steps - -When an integration is discovered, their respective discovery step is invoked with the discovery information. The step will have to check the following things: - - - Make sure there are no other instances of this config flow in progress of setting up the discovered device. This can happen if there are multiple ways of discovering that a device is on the network. - - Make sure that the device is not already set up. - - Invoking a discovery step should never result in a finished flow and a config entry. Always confirm with the user. - - ## Discoverable integrations that require no authentication - -If your integration is discoverable without requiring any authentication, you'll be able to use the Discoverable Flow that is built-in. This flow offers the following features: - - - Detect if devices/services can be discovered on the network before finishing the config flow. - - Support all manifest-based discovery protocols. - - Limit to only 1 config entry. It is up to the config entry to discover all available devices. - -```python -"""Config flow for LIFX.""" -from homeassistant.helpers import config_entry_flow -from homeassistant import config_entries - -import aiolifx - -from .const import DOMAIN - - -async def _async_has_devices(hass): - """Return if there are devices that can be discovered.""" - lifx_ip_addresses = await aiolifx.LifxScan(hass.loop).scan() - return len(lifx_ip_addresses) > 0 - - -config_entry_flow.register_discovery_flow( - # Domain of your integration - DOMAIN, - # Title of the created config entry - 'LIFX', - # async method that returns a boolean if devices/services are found - _async_has_devices, - # Connection class of the integration - config_entries.CONN_CLASS_LOCAL_POLL -) -``` - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` - -When the translations are merged into Home Assistant, they will be automatically uploaded to [Lokalise](https://lokalise.co/) where the translation team will help to translate them in other languages. [More info on translating Home Assistant.](internationalization_translation.md) diff --git a/website/versioned_docs/version-0.95.0/development_environment.md b/website/versioned_docs/version-0.95.0/development_environment.md deleted file mode 100644 index cd69b523..00000000 --- a/website/versioned_docs/version-0.95.0/development_environment.md +++ /dev/null @@ -1,120 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.95.0-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example CentOS would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Due to Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run - -```bash -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is set up, perform install as for Linux. - -```bash -$ sudo apt-get update -$ sudo apt-get install python3-pip python3-dev python3-venv -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```bash -$ mkdir -p ../config -$ hass -c ../config -``` - -### Developing on macOS - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 autoconf -``` - -Then install ffmpeg: - -```bash -$ brew install ffmpeg -``` - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv venv -$ source venv/bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```bash -$ hass -``` - -## Logging - -By default logging in Home Assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` diff --git a/website/versioned_docs/version-0.95.0/development_testing.md b/website/versioned_docs/version-0.95.0/development_testing.md deleted file mode 100644 index 7da81a41..00000000 --- a/website/versioned_docs/version-0.95.0/development_testing.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Testing your code -id: version-0.95.0-development_testing -original_id: development_testing ---- - -As it states in the [Style guidelines section](development_guidelines.md) all code is checked to verify the following: - -- All the unit tests pass -- All code passes the checks from the linting tools - -Local testing is done using Tox, which has been installed as part of running `script/setup` in the [virtual environment](development_environment.md). To start the tests, activate the virtual environment and simply run the command: - -```bash -$ tox -``` -**Important:** Run `tox` before you create your pull request to avoid annoying fixes. - -Running Tox will run unit tests against the locally available Pythons, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one tox target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py36` runs unit tests only on Python 3.6. - -Tox uses virtual environments under the hood to create isolated testing environments. The tox virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell Tox to recreate the virtual environments. - -macOS users may see an `Error creating virtualenv` when runnng `tox`. If this occurs, install the [tox-venv](https://pypi.org/project/tox-venv/) package using the command `pip install tox-venv` and try again. - -### Adding new dependencies to test environment - -If you are working on tests for a component or platform and you need the dependencies available inside the Tox environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments. - -### Running single tests using Tox - -You can pass arguments via Tox to py.test to be able to run single test suites or test files. Replace `py36` with the Python version that you use. - -```bash -# Stop after the first test fails -$ tox -e py36 -- tests/test_core.py -x -# Run test with specified name -$ tox -e py36 -- tests/test_core.py -k test_split_entity_id -# Fail a test after it runs for 2 seconds -$ tox -e py36 -- tests/test_core.py --timeout 2 -# Show the 10 slowest tests -$ tox -e py36 -- tests/test_core.py --duration=10 -``` - -### Testing outside of Tox - -Running tox will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without Tox, you'll need to install the test dependencies into your Python environment: - -```bash -$ pip3 install -r requirements_test_all.txt -c homeassistant/package_constraints.txt -``` - -Now that you have all test dependencies installed, you can run tests on individual files: - -```bash -$ flake8 homeassistant/core.py -$ pylint homeassistant/core.py -$ pydocstyle homeassistant/core.py -$ py.test tests/test_core.py -``` - -You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script: - -```bash -$ script/lint -``` - -### Preventing Linter Errors - -Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them! - -```bash -$ pip3 install flake8 flake8-docstrings -$ flake8 --install-hook=git -``` - -The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8. - -### Notes on PyLint and PEP8 validation - -If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member. diff --git a/website/versioned_docs/version-0.95.0/device_registry_index.md b/website/versioned_docs/version-0.95.0/device_registry_index.md deleted file mode 100644 index 018d151a..00000000 --- a/website/versioned_docs/version-0.95.0/device_registry_index.md +++ /dev/null @@ -1,87 +0,0 @@ ---- -title: Device Registry -sidebar_label: Introduction -id: version-0.95.0-device_registry_index -original_id: device_registry_index ---- - -The device registry is a registry where Home Assistant keeps track of devices. A device is represented in Home Assistant via one or more entities. For example, a battery-powered temperature and humidity sensor might expose entities for temperature, humidity and battery level. - -Device registry overview - -## What is a device? - -A device in Home Assistant represents a physical device that has its own control unit. The control unit itself does not have to be smart, but it should be in control of what happens. For example, an Ecobee thermostat with 4 room sensors equals 5 devices in Home Assistant, one for the thermostat including all sensors inside it, and one for each sensor. Each device exists in a specific geographical area, and may have more than one input or output within that area. - -If you connect a sensor to another device to read some of its data, it should still be represented as two different devices. The reason for this is that the sensor could be moved to read the data of another device. - -A device that offers multiple endpoints, where parts of the device sense or output in different areas, should be split into separate devices and refer back to parent device with the `via_device` attribute. This allows the separate endpoints to be assigned to different areas in the building. - -> Although not currently available, we could consider offering an option to users to merge devices. - -## Device properties - -| Attribute | Description | -| --------- | ----------- | -| id | Unique ID of device (generated by Home Assistant) -| name | Name of this device -| connections | A set of tuples of `(connection_type, connection identifier)`. Connection types are defined in the device registry module. -| identifiers | Set of identifiers. They identify the device in the outside world. An example is a serial number. -| manufacturer | The manufacturer of the device. -| model | The model of the device. -| config_entries | Config entries that are linked to this device. -| sw_version | The firmware version of the device. -| via_device | Identifier of a device that routes messages between this device and Home Assistant. Examples of such devices are hubs, or parent devices of a sub-device. This is used to show device topology in Home Assistant. -| area_id | The Area which the device is placed in. - -## Defining devices - -> Entity device info is only read if the entity is loaded via a [config entry](config_entries_index.md). - -Each entity is able to define a device via the `device_info` property. This property is read when an entity is added to Home Assistant via a config entry. A device will be matched up with an existing device via supplied identifiers and connections, like serial numbers or MAC addresses. - -```python -# Inside a platform -class HueLight(LightEntity): - - @property - def device_info(self): - return { - 'identifiers': { - # Serial numbers are unique identifiers within a specific domain - (hue.DOMAIN, self.unique_id) - }, - 'name': self.name, - 'manufacturer': self.light.manufacturername, - 'model': self.light.productname, - 'sw_version': self.light.swversion, - 'via_device': (hue.DOMAIN, self.api.bridgeid), - } - -``` - -Components are also able to register devices in the case that there are no entities representing them. An example is a hub that communicates with the lights. - -```python -# Inside a component -from homeassistant.helpers import device_registry as dr - -device_registry = await dr.async_get_registry(hass) - -device_registry.async_get_or_create( - config_entry_id=entry.entry_id, - connections={ - (dr.CONNECTION_NETWORK_MAC, config.mac) - }, - identifiers={ - (DOMAIN, config.bridgeid) - }, - manufacturer='Signify', - name=config.name, - model=config.modelid, - sw_version=config.swversion, -) -``` diff --git a/website/versioned_docs/version-0.95.0/documentation_standards.md b/website/versioned_docs/version-0.95.0/documentation_standards.md deleted file mode 100644 index 262f19b1..00000000 --- a/website/versioned_docs/version-0.95.0/documentation_standards.md +++ /dev/null @@ -1,125 +0,0 @@ ---- -title: Standards -id: version-0.95.0-documentation_standards -original_id: documentation_standards ---- - -To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation. - -## General Documentation - -* The language of the documentation should be American-English. -* Don't put two spaces after a period and avoid the "Oxford comma". -* There is no limit for the line length. You are allowed to write in a flowing text style. This will make it easier to use the GitHub online editor in the future. -* Be objective and not gender favoring, polarizing, race related or religion inconsiderate. -* The case of brand names, services, protocols, components and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select". -* Do not use ALL CAPITALS for emphasis - use italics instead. - -## Component and Platform Pages - -* The **Configuration Variables** section must use the `{% configuration %}` tag. -* Configuration variables must document the requirement status (`false` or `true`). -* Configuration variables must document the default value, if any. -* Configuration variables must document the accepted value types (see [Configuration variables details](documentation_create_page.md#configuration)). - * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`). -* Use YAML sequence syntax in the sample code if it is supported. -* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated. - * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`. - * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note. -* Component and platform names should be a link to their respective documentation pages. - -Example configuration block - -```yaml -{% configuration %} -some_key: - description: This is a description of what this key is for. - required: false - type: string - default: Optional default value - leave out if there isn't one -{% endconfiguration %} -``` - -## Templates - -* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the `{% raw %}` tag. -* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`. -* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)): - * `friendly_name` - * Single-line templates: - * `value_template` - * `level_template` - * `icon_template` - * Children of `data_template` -* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks): - * Strings inside of templates: - * States - * Entity IDs - * `unit_of_measurement` -* No whitespace around pipe character (`|`) for Jinja2 filters. -* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}). -* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}). -* Do not quote values for: - * `device_class` - * `platform` - * `condition` - * `service` - -## Renaming Pages - -It can happen that a component or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old component/platform name, to the page in a [note](/developers/documentation/create_page/#html). - -```text ---- -... -redirect_from: /getting-started/android/ ---- -``` - -Adding a redirect also applies if you move content around in the [documentation](/docs/). - -## Single vs. Double Quotation Marks - -Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required). - -### Examples - -#### Double Quotes Outside, Single Quotes Inside (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}" -``` - -#### Single Quotes Outside, Double Quotes Inside (Invalid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}' -``` - -#### Multi-Line Template (Valid) - - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: >- - {% if trigger.to_state.name == 'Dale\'s Bedroom' %} - Someone's in your base, killing your noobs! - {% else %} - It's just another door. - {% endif %} -``` - diff --git a/website/versioned_docs/version-0.95.0/frontend_development.md b/website/versioned_docs/version-0.95.0/frontend_development.md deleted file mode 100644 index d201c898..00000000 --- a/website/versioned_docs/version-0.95.0/frontend_development.md +++ /dev/null @@ -1,105 +0,0 @@ ---- -title: Frontend development -sidebar_label: Development -id: version-0.95.0-frontend_development -original_id: frontend_development ---- - -The Home Assistant frontend is built using web components. For more background about our technology choices, [see this blog post](https://developers.home-assistant.io/blog/2019/05/22/internet-of-things-and-the-modern-web.html). - -> Do not use development mode in production. Home Assistant uses aggressive caching to improve the mobile experience. This is disabled during development so that you do not have to restart the server in between changes. - -## Setting up the environment - -### Getting the code - -First step is to fork the [home-assistant-polymer repository][hass-polymer] and add the upstream remote. You can place the forked repository anywhere on your system. - -```bash -$ git clone git@github.com:YOUR_GIT_USERNAME/home-assistant-polymer.git -$ cd home-assistant-polymer -$ git remote add upstream https://github.com/home-assistant/home-assistant-polymer.git -``` - -### Configuring Home Assistant - -You will need to have an instance of Home Assistant set up. See our guide on [setting up a development environment](https://developers.home-assistant.io/docs/en/development_environment.html). - -Next step is to configure Home Assistant to use the development mode for the frontend. Do this by updating the frontend config in your `configuration.yaml` and set the path to the home-assistant-polymer repository that you cloned in the last step: - -```yaml -frontend: - # Example absolute path: /home/paulus/dev/hass/home-assistant-polymer - development_repo: -``` - -### Installing Node.js - -Node.js is required to build the frontend. The preferred method of installing node.js is with [nvm](https://github.com/creationix/nvm). Install nvm using the instructions in the [README](https://github.com/creationix/nvm#install-script), and install the correct node.js by running the following command: - -```bash -$ nvm install -``` - -[Yarn](https://yarnpkg.com/en/) is used as the package manager for node modules. [Install yarn using the instructions here.](https://yarnpkg.com/en/docs/install) - -Next, development dependencies need to be installed to bootstrap the frontend development environment. First activate the right Node version and then download all the dependencies: - -```bash -$ nvm use -$ script/bootstrap -``` - -## Development - -During development, you will need to run the development script to maintain a development build of the frontend that auto updates when you change any of the source files. To run this server, run: - -```bash -$ nvm use -$ script/develop -``` - -Make sure you have cache disabled and correct settings to avoid stale content: - -> Instructions are for Google Chrome - -1. Disable cache by ticking the box in `Network` > `Disable cache` - -

- -

- -2. Enable Bypass for network in `Application` > `Service Workers` > `Bypass for network` - -

- -

- -## Creating pull requests - -If you're planning on issuing a PR back to the Home Assistant codebase you need to fork the polymer project and add your fork as a remote to the Home Assistant Polymer repo. - -```bash -$ git remote add fork -``` - -When you've made your changes and are ready to push them change to the working directory for the polymer project and then push your changes - -``` bash -$ git add -A -$ git commit -m "Added new feature X" -$ git push -u fork HEAD -``` - -## Building the Polymer frontend - -If you're making changes to the way the frontend is packaged, it might be necessary to try out a new packaged build of the frontend in the main repository (instead of pointing it at the frontend repo). To do so, first build a production version of the frontend by running `script/build_frontend`. - -To test it out inside Home assistant, run the following command from the main Home Assistant repository: - -```bash -$ pip3 install -e /path/to/home-assistant-polymer/ -$ hass --skip-pip -``` - -[hass-polymer]: https://github.com/home-assistant/home-assistant-polymer diff --git a/website/versioned_docs/version-0.95.0/hassio_addon_tutorial.md b/website/versioned_docs/version-0.95.0/hassio_addon_tutorial.md deleted file mode 100644 index 1859723c..00000000 --- a/website/versioned_docs/version-0.95.0/hassio_addon_tutorial.md +++ /dev/null @@ -1,182 +0,0 @@ ---- -title: Tutorial: Making your first add-on -id: version-0.95.0-hassio_addon_tutorial -original_id: hassio_addon_tutorial ---- - -So you've got Home Assistant going and you've been enjoying the built-in add-ons but you're missing this one application. Time to make your own add-on! In Hass.io 0.24 we introduced the option to have local add-ons be build on your device. This is great for developing new add-ons locally. - -To get started with developing add-ons, we first need access to where Hass.io looks for local add-ons. For this you can use the Samba add-on or the SSH add-on. - -For Samba, once you have enabled and started it, your Hass.io instance will show up in your local network tab and share a folder called "addons". This is the folder to store your custom add-ons. - -If you are on macOS and the folder is not showing up automatically, go to Finder and press CMD+K then enter 'smb://hassio.local' - -![Screenshot of Windows Explorer showing a folder on the Hass.io server](/img/en/hass.io/tutorial/samba.png) - -For SSH, you will have to install it. Before you can start it, you will have to have a private/public key pair and store your public key in the add-on config ([see docs for more info][ssh]). Once started, you can SSH to Hass.io and store your custom add-ons in "/addons". - -![Screenshot of Putty connected to Hass.io](/img/en/hass.io/tutorial/ssh.png) - -Once you have located your add-on directory, it's time to get started! - -[ssh]: https://www.home-assistant.io/addons/ssh/ - -## Step 1: The basics - - - Create a new directory called `hello_world` - - Inside that directory create three files. - -`Dockerfile`: -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -`config.json`: -```json -{ - "name": "Hello world", - "version": "1", - "slug": "hello_world", - "description": "My first real add-on!", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {} -} -``` - -`run.sh`: -```bash -echo Hello world! -``` -Make sure your editor is using UNIX-like line breaks (LF), not Dos/Windows (CRLF). - -## Step 2: Installing and testing your add-on - -Now comes the fun part, time to open the Hass.io UI and install and run your add-on. - - - Open the Home Assistant frontend - - Go to the Hass.io panel - - On the top right click the shopping basket to go to the add-on store. - -![Screenshot of the Hass.io main panel](/img/en/hass.io/screenshots/main_panel_addon_store.png) - - - On the top right click the refresh button - - You should now see a new card called "Local" that lists your add-on! - -![Screenshot of the local repository card](/img/en/hass.io/screenshots/local_repository.png) - - - Click on your add-on to go to the add-on details page. - - Install your add-on - - Start your add-on - - Refresh the logs of your add-on, you should now see "Hello world!" in your logs. - -![Screenshot of the add-on logs](/img/en/hass.io/tutorial/addon_hello_world_logs.png) - -### I don't see my add-on?! - -Oops! You clicked refresh in the store and your add-on didn't show up. Or maybe you just updated an option, clicked refresh and saw your add-on disappear. - -When this happens, it means that your `config.json` is invalid. It's either invalid JSON or one of the specified options is incorrect. To see what went wrong, go to the Hass.io panel and in the supervisor card click on "View logs". This should bring you to a page with the logs of the supervisor. Scroll to the bottom and you should be able to find the validation error. - -Once you fixed the error, go to the add-on store and click refresh again. - -## Step 3: Hosting a server - -Until now we've been able to do some basic stuff, but it's not very useful yet. So let's take it one step further and host a server that we expose on a port. For this we're going to use the built-in HTTP server that comes with Python 3. - -To do this, we will need to update our files as follows: - - - `Dockerfile`: Install Python 3 - - `config.json`: Make the port from the container available on the host - - `run.sh`: Run the Python 3 command to start the HTTP server - -Add to your `Dockerfile` before `RUN`: - -``` -# Install requirements for add-on -RUN apk add --no-cache python3 - -# Python 3 HTTP Server serves the current working dir -# So let's set it to our add-on persistent data directory. -WORKDIR /data -``` - -Add "ports" to `config.json`. This will make TCP on port 8000 inside the container available on the host on port 8000. - -```json -{ - "name": "Hello world", - "version": "0.2", - "slug": "hello_world", - "description": "My first real add-on!", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {}, - "ports": { - "8000/tcp": 8000 - } -} -``` - -Update `run.sh` to start the Python 3 server: - -``` -python3 -m http.server 8000 -``` - -## Step 4: Installing the update - -Since we updated the version number in our `config.json`, Home Assistant will show an update button when looking at the add-on details. You might have to refresh your browser or click the refresh button in the add-on store for it to show up. If you did not update the version number, you can also uninstall and install the add-on again. After installing the add-on again, make sure you start it. - -Now navigate to [http://hassio.local:8000](http://hassio.local:8000) to see our server in action! - -![Screenshot of the file index served by the add-on](/img/en/hass.io/tutorial/python3-http-server.png) - -## Bonus: Working with add-on options - -In the screenshot you've probably seen that our server only served up 1 file: `options.json`. This file contains the user configuration for this add-on. Because we specified an empty "config" and "schema" in our `config.json`, the file is currently empty. - -Let's see if we can get some data into that file! - -To do this, we need to specify the default options and a schema for the user to change the options. - -Change the options and schema entries in your `config.json` with the following: - -```json -{ - … - - "options": { - "beer": true, - "wine": true, - "liquor": false, - "name": "world", - "year": 2017 - }, - "schema": { - "beer": "bool", - "wine": "bool", - "liquor": "bool", - "name": "str", - "year": "int" - }, - - … -} -``` - -Refresh the add-on store and re-install your add-on. You will now see the options available in the add-on config screen. When you now go back to our Python 3 server and download `options.json`, you'll see the options you set. [Example of how options.json can be used inside `run.sh`](https://github.com/home-assistant/hassio-addons/blob/master/mosquitto/run.sh#L4-L6) diff --git a/website/versioned_docs/version-0.95.0/hassio_debugging.md b/website/versioned_docs/version-0.95.0/hassio_debugging.md deleted file mode 100644 index 32f7ea84..00000000 --- a/website/versioned_docs/version-0.95.0/hassio_debugging.md +++ /dev/null @@ -1,91 +0,0 @@ ---- -title: Debugging Hass.io -id: version-0.95.0-hassio_debugging -original_id: hassio_debugging ---- - -> This section is not for end users. End users should use the [SSH add-on] to SSH into Hass.io. This is for developers of Hass.io. Do not ask for support if you are using these options. - -[SSH add-on]: https://www.home-assistant.io/addons/ssh/ - -The following debug tips and tricks are for developers who are running the Hass.io image and are working on the base image. If you use the generic Linux installer script, you should be able to access your host and logs as per your host. - -## Debug Supervisor - -Visual Studio Code config: -```json -{ - "version": "0.2.0", - "configurations": [ - { - "name": "Hass.io remote debug", - "type": "python", - "request": "attach", - "port": 33333, - "host": "IP", - "pathMappings": [ - { - "localRoot": "${workspaceFolder}", - "remoteRoot": "/usr/src/hassio" - } - ] - } - ] -} -``` - -You need set the dev mode on supervisor and enable debug with options. You need also install the Remote debug Add-on from Developer Repository to expose the debug port to Host. - -## SSH access to the host -> SSH access through the [SSH add-on] (which will give you SSH access through port 22) will not provide you with all the necessary privileges, and you will be asked for a username and password when typing the 'login' command. You need to follow the steps below, which will setup a separate SSH access through port 22222 with all necessary privileges. - -### resinOS based Hass.io (deprecated) -Create an `authorized_keys` file containing your public key, and place it in the root of the boot partition of your SD card. See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. Once the device is booted, you can access your device as root over SSH on port 22222. - -### HassOS based Hass.io -Use a USB drive formatted with FAT, ext4, or NTFS and name it CONFIG (case sensitive). Create an `authorized_keys` file (no extension) containing your public key, and place it in the root of the USB drive. File needs to be ANSI encoded (not UTF-8) and must have Unix line ends (LF), not Windows (CR LF). See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. From the UI, navigate to the hass.io system page and choose "Import from USB". You can now access your device as root over SSH on port 22222. Alternatively, the file will be imported from the USB when the hass.io device is rebooted. - -> Make sure when you are copying the public key to the root of the USB drive that you rename the file correctly to `authorized_keys` with no `.pub` file extension. - -You should then be able to SSH into your Hass.io device. On Mac/Linux, use: - -``` -ssh root@hassio.local -p 22222 -``` - -You will initially be logged in to Hass.io CLI for HassOS where you can perform normal [CLI functions]. If you need access to the host system use the 'login' command. [Hass.io OS] is a hypervisor for Docker. See the [Hass.io Architecture] documentation for information regarding the Hass.io supervisor. The supervisor offers an API to manage the host and running the Docker containers. Home Assistant itself and all installed addon's run in separate Docker containers. - -[CLI functions]: https://www.home-assistant.io/hassio/commandline/ -[Hass.io OS]: https://github.com/home-assistant/hassos -[Hass.io Architecture]: https://developers.home-assistant.io/docs/en/architecture_hassio.html - -## Checking the logs - -```bash -# Logs from the supervisor service on the Host OS -journalctl -f -u hassos-supervisor.service - -# Hass.io supervisor logs -docker logs hassos_supervisor - -# Home Assistant logs -docker logs homeassistant -``` - -## Accessing the container bash - -```bash -docker exec -it homeassistant /bin/bash -``` - -[windows-keys]: https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-putty-on-digitalocean-droplets-windows-users - -### Generating SSH Keys - -Windows instructions for how to generate and use private/public keys with Putty are [here][windows-keys]. Instead of the droplet instructions, add the public key as per above instructions. - -Alternative instructions, for Mac, Windows and Linux can be found [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#platform-mac). - -Follow steps 1-4 under 'Generating a new SSH key' (The other sections are not applicable to Hass.io and can be ignored.) - -Step 3 in the link above, shows the path to the private key file `id_rsa` for your chosen operating system. Your public key, `id_rsa.pub`, is saved in the same folder. Next, select all text from text box "Public key for pasting into the authorized_keys file" and save it to the root of your USB drive as `authorized_keys`. diff --git a/website/versioned_docs/version-0.96.0/asyncio_categorizing_functions.md b/website/versioned_docs/version-0.96.0/asyncio_categorizing_functions.md deleted file mode 100644 index da12fc4a..00000000 --- a/website/versioned_docs/version-0.96.0/asyncio_categorizing_functions.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -title: Categorizing Functions -id: version-0.96.0-asyncio_categorizing_functions -original_id: asyncio_categorizing_functions ---- - -A piece of work within Home Assistant is represented by a function that will be invoked. It will either run inside our event loop or inside our thread pool, depending on if it is async safe. - -Home Assistant uses the convention that all functions that must be run from within the event loop are prefixed with `async_`. - -## The coroutine function - -Coroutines are special functions based on Python’s generators syntax which allows them to suspend execution while waiting on a result. - -Invoking a coroutine function will return a Generator object back, but will not actually begin execution. This object will execute the task when it is either awaited (from within another coroutine) or it is scheduled on the event loop. - -To declare a function a coroutine, add `async` before the `def` of the function definition. - -```python -async def async_look_my_coroutine(target): - result = await entity.async_turn_on() - if result: - print("hello {}".format(target)) - -hass.loop.create_task(async_look_my_coroutine("world")) -``` - -In this example, we schedule the coroutine by calling `hass.loop.create_task`. This will add the coroutine to the queue of tasks to be run. When the event loop is running `async_look_my_coroutine` it will suspend the task when `await entity.async_turn_on()` is called. At that point a new task will be scheduled to execute `entity.async_turn_on()`. When that job has been executed, `async_look_my_coroutine` will resume. - -## The callback function - -This is a normal function that is considered safe to be run from within the event loop. A callback is unable to suspend itself and thus cannot do any I/O or call a coroutine. A callback is capable of scheduling a new task but it will not be able to wait for the results. - -To declare a function as a callback, import the callback annotation from the core package and annotate your function. - -A common use case for a callback in Home Assistant is as a listener for an event or a service call. It can process the incoming information and then schedule the right calls to be made. Example from the automation component. - -```python -from homeassistant.core import callback - -@callback -def async_trigger_service_handler(service_call): - """Handle automation trigger service calls.""" - vars = service_call.data.get(ATTR_VARIABLES) - for entity in component.async_extract_from_service(service_call): - hass.loop.create_task(entity.async_trigger(vars, True)) -``` - -In this example, `entity.async_trigger` is a coroutine function. Invoking the coroutine function will return a coroutine task. The passed in parameters will be used when the task gets executed. - -To execute the task we have to schedule it for execution on the event loop. This is done by calling `hass.loop.create_task`. - -### Why even have callbacks? - -You might wonder, if a coroutine can do everything a callback can do, why even have a callback. The reason is performance and better state consistency of the core API objects. - -When coroutine A waits for coroutine B, it will suspend itself and schedule a new task to run B. This means that the event loop is now running A, B and then A again. If B is a callback, A will never have to suspend itself and thus the event loop is just running A. The consistency implication is that other events queued to run on the event loop continue to wait until callbacks complete, but will be interleaved when yielding to another coroutine. - -## Event loop and thread safe - -These are functions that are safe to run both in a thread and inside the event loop. These functions are usually performing a computation or transform data in memory. Anything that does I/O does not fall under this category. Many standard library functions fall in this category. For example generating the sum of a set of numbers using sum or merging two dictionaries. - -There is no special annotation to mark functions as part of this category and care should be taken when using these functions from inside the event loop. When in doubt, look at their implementation. - -## Other functions - -These are all the functions that did not fit in the previous categories. These functions are either thread-safe or not considered safe to be run within the event loop. These are functions that use sleep, or perform I/O. - -There is no special annotation necessary to be considered part of this category. diff --git a/website/versioned_docs/version-0.96.0/development_environment.md b/website/versioned_docs/version-0.96.0/development_environment.md deleted file mode 100644 index 44cfda58..00000000 --- a/website/versioned_docs/version-0.96.0/development_environment.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.96.0-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example CentOS would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Due to Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run - -```bash -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is set up, perform install as for Linux. - -```bash -$ sudo apt-get update -$ sudo apt-get install python3-pip python3-dev python3-venv -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```bash -$ mkdir -p ../config -$ hass -c ../config -``` - -### Developing on macOS - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 autoconf -``` - -Then install ffmpeg: - -```bash -$ brew install ffmpeg -``` - -### Developing with devcontainer - -The devcontainer is a preconfigured development environment with all the tools you need. - -**Prerequisites** - -- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) -- [Docker](https://docs.docker.com/install/) -- [Visual Studio code](https://code.visualstudio.com/) -- [Remote - Containers (VSC Extension)](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) - -[More info about requirements and devcontainer in general](https://code.visualstudio.com/docs/remote/containers#_getting-started) - -**Getting started:** - -1. Fork the repository. -1. Clone the repository to your computer. -1. Open the repository using Visual Studio code. - -When you open this repository with Visual Studio code you are asked to "Reopen in Container", this will start the build of the container. - -_If you don't see this notification, open the command pallet and select `Remote-Containers: Reopen Folder in Container`._ - -The devcontainter comes with some useful tasks to help you with development, you can start these tasks by opening the command pallet and select `Tasks: Run Task` then select the task you want to run. - -Running tasks like `Preview` can be restarted by opening the command pallet and selecting `Tasks: Restart Running Task`, then select the task you want to restart. - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv venv -$ source venv/bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```bash -$ hass -``` - -## Logging - -By default logging in Home Assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` diff --git a/website/versioned_docs/version-0.96.0/documentation_create_page.md b/website/versioned_docs/version-0.96.0/documentation_create_page.md deleted file mode 100644 index 23c98d89..00000000 --- a/website/versioned_docs/version-0.96.0/documentation_create_page.md +++ /dev/null @@ -1,135 +0,0 @@ ---- -title: Create a new page -id: version-0.96.0-documentation_create_page -original_id: documentation_create_page ---- - -For a platform or integration page, the fastest way is to make a copy of an existing page and edit it. The [Integration overview](https://www.home-assistant.io/components/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages. - -Please honor the [Standards](documentation_standards.md) we have for the documentation. - -If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers. - -```text ---- -title: "Awesome Sensor" -description: "home-assistant.io web presence" -ha_release: "0.38" -ha_category: Sensor -ha_iot_class: "Local Polling" -ha_qa_scale: silver -ha_config_flow: true ---- - -Content... Written in markdown. - -### Title Header -... -``` - -Additional keys for the file header: - -- `logo`: Please check the separate section below. -- `ha_release`: The release when the integration was included, e.g., "0.38". If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`. -- `ha_category`: This entry is used to group the integration on the [Integration overview](https://www.home-assistant.io/components/). -- `ha_iot_class`: [IoT class](https://www.home-assistant.io/blog/2016/02/12/classifying-the-internet-of-things) is the classifier for the device's behavior. -- `ha_qa_scale`: [Quality scale](https://www.home-assistant.io/docs/quality_scale/) is the representation of the integration's quality. -- `ha_config_flow`: Set to `true` if the integration has a [Data Entry Flow](https://developers.home-assistant.io/docs/en/data_entry_flow_index.html), omit otherwise. - -There are [pre-defined variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation. - -A couple of points to remember: - -- Document the needed steps to retrieve API keys or access token for the third party service or device if needed. -- Add screenshots to support the user where it makes sense. -- Add the type of the device(s) (incl. firmware) you have tested when you know that there are multiple out there. - -### Configuration - -Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file. - -The **Configuration Variables** section must use the `{% configuration %} ... {% endconfiguration %}` tag. - -```text -{% configuration %} -api_key: - description: The API key to access the service. - required: true - type: string -name: - description: Name to use in the frontend. - required: false - default: The default name to use in the frontend. - type: string -monitored_conditions: - description: Conditions to display in the frontend. - required: true - type: map - keys: - weather: - description: A human-readable text summary. - temperature: - description: The current temperature. -{% endconfiguration %} -``` - -Available keys: - -- **`description:`**: That the variable is about. -- **`required:`**: If the variable is required. - -```text -required: true #=> Required -required: false #=> Optional -required: inclusive #=> Inclusive -required: exclusive #=> Exclusive -required: any string here #=> Any string here -``` -- **`type:`**: The type of the variable. Allowed entries: `boolean`, `string`, `integer`, `float`, `time`, `template`, `device_class`, `icon` or `map`/`list` (for a list of entries). For multiple possibilities use `[string, integer]`. If you use `map`/`list` then should define `keys:` (see the [`template` sensor](https://www.home-assistant.io/components/sensor.template/) for an example). If you use `boolean`, then `default:` must be defined. -- **`default:`**: The default value for the variable. - -### Embedding Code - -You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in back-ticks. - -When you're writing code that is to be executed on the terminal, do not prefix them with `$`, since this makes it hard to copy and paste the commands. However, an exception is made when there is a need to distinguish between typed commands and command output. In those cases, prefixing the commands with a `$` is required. - -### Templates - -For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) [Jinja](http://jinja.pocoo.org/) is used. Check the [Documentation Standards](documentation_standards.md) for further details. - -If you are don't escape templates then they will be rendered and appear blank on the website. - -### HTML - -The direct usage of HTML is supported but not recommended. The note boxes are an exception. - -```html -
- You need to enable telnet on your router. -
-``` - -Please note, if you want to use Markdown inside an HTML block, it has to be surrounded by a new line. - -```html -
- You need to enable [**telnet**](https://en.wikipedia.org/wiki/Telnet) on your router. -
-``` - -### Images, icons and logos - -The images which are displayed on the pages are stored in various directories according to their purpose. If you want to use a logo and placed `logo:` in the file header then this image should be stored in `source/images/supported_brands`. The background must be transparent. - -| Type | Location | -| :----------- |:----------------------------------------------| -| logos | source/images/supported_brands | -| blog | source/images/blog | -| screenshots | source/images/components | - -Not everything (product, integration, etc.) should have a logo. To show something for internal parts of Home Assistant we are using the [Material Design Icons](https://materialdesignicons.com/). - -### Linking From The Sidebar - -If you are adding a new page that requires linking from the sidebar, you need to edit the `docs_navigation.html` file in `source/_includes/asides/docs_navigation.html`. diff --git a/website/versioned_docs/version-0.96.0/documentation_index.md b/website/versioned_docs/version-0.96.0/documentation_index.md deleted file mode 100644 index 2e025c54..00000000 --- a/website/versioned_docs/version-0.96.0/documentation_index.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Documentation -id: version-0.96.0-documentation_index -original_id: documentation_index ---- - -The user documentation is located at [https://www.home-assistant.io](https://www.home-assistant.io). This section here is the place where we provide documentation and additional details about creating or modifying content. - -The [home-assistant.io](https://home-assistant.io) website is built using [Jekyll](http://github.com/mojombo/jekyll) and [these dependencies](https://pages.github.com/versions/). The pages are written in [Markdown](http://daringfireball.net/projects/markdown/). To add a page, you don't need to know HTML. - -You can use the "**Edit this page on GitHub**" link to edit pages without creating a fork. Keep in mind that you can't upload images while working this way. You work on your change and propose it via a Pull Request (PR). - -Once you've created a Pull Request (PR), you can see a preview of the proposed changes by clicking *Details* against Netlify checker in the checkers section of the PR as soon as deployment is complete. - -For larger changes, we suggest that you clone the website repository. This way, you can review your changes locally. The process of working on the website is no different from working on Home Assistant itself. - -To test your changes locally, you need to install **Ruby** and its dependencies (gems): - -- [Install Ruby](https://www.ruby-lang.org/en/documentation/installation/) if you don't have it already. Ruby version 2.5.0 or higher is required. -- Install `bundler`, a dependency manager for Ruby: `$ gem install bundler` (You might have to run this command as `sudo`). -- Fork the home-assistant.io [git repository](https://github.com/home-assistant/home-assistant.io). -- In your home-assistant.io root directory, run `$ bundle` to install the gems you need. - -- Shortcut for Fedora: `$ sudo dnf -y install gcc-c++ ruby ruby-devel rubygem-bundler rubygem-json && bundle` -- Shortcut for Debian/Ubuntu: `$ sudo apt-get install ruby ruby-dev ruby-bundler ruby-json g++ zlib1g-dev && bundle` - -Then you can work on the documentation: - -- Run `bundle exec rake generate` to generate the very first preview. This will take a minute. -- Create/edit/update a page. The integration/platforms documentation is located in `source/_components/`. `source/_docs/` contains the Home Assistant documentation itself. -- Test your changes to home-assistant.io locally: run `bundle exec rake preview` and navigate to [http://127.0.0.1:4000](http://127.0.0.1:4000). While this command is working, any changes to a file are automatically detected and will update the affected pages. You will have to manually reload them in the browser though. -- Create a Pull Request (PR) against the **next** branch of home-assistant.io if your documentation is a new feature, platform, or integration. -- Create a Pull Request (PR) against the **current** branch of home-assistant.io if you fix stuff, create Cookbook entries, or expand existing documentation. - -The site generated by `bundle exec rake` is only available locally. If you are developing on a headless machine, use port forwarding: - -```bash -$ ssh -L 4000:localhost:4000 user_on_headless_machine@ip_of_headless_machine -``` - -## Speeding up site generation - -Every release we post long changelogs to the website. This slows down generation of the website a bit. We've include some tools to temporarily exclude integrations and blog posts that you're not working on out of the way. - -```bash -bundle exec rake isolate[filename-of-blogpost-or-integration] -``` - -When you're done working on the site, run the following command to move the pages back again: - -```bash -bundle exec rake integrate -``` diff --git a/website/versioned_docs/version-0.96.0/documentation_standards.md b/website/versioned_docs/version-0.96.0/documentation_standards.md deleted file mode 100644 index 20282e9c..00000000 --- a/website/versioned_docs/version-0.96.0/documentation_standards.md +++ /dev/null @@ -1,123 +0,0 @@ ---- -title: Standards -id: version-0.96.0-documentation_standards -original_id: documentation_standards ---- - -To ensure that the documentation for Home Assistant is consistent and easy to follow for both novice and expert users, we ask that you follow a very strict set of standards for developing the documentation. - -## General Documentation - -* The language of the documentation should be American-English. -* Don't put two spaces after a period and avoid the "Oxford comma". -* There is no limit for the line length. You are allowed to write in a flowing text style. This will make it easier to use the GitHub online editor in the future. -* Be objective and not gender favoring, polarizing, race related or religion inconsiderate. -* The case of brand names, services, protocols, integrations and platforms must match its respective counterpart. e.g., "Z-Wave" **not** "Zwave", "Z-wave", "Z Wave" or "ZWave". Also, "Input Select" **not** "input select" or "Input select". -* Do not use ALL CAPITALS for emphasis - use italics instead. - -## Integration and Platform Pages - -* The **Configuration Variables** section must use the `{% configuration %}` tag. -* Configuration variables must document the requirement status (`false` or `true`). -* Configuration variables must document the default value, if any. -* Configuration variables must document the accepted value types (see [Configuration variables details](documentation_create_page.md#configuration)). - * For configuration variables that accept multiple types, separate the types with a comma (i.e. `string, int`). -* Use YAML sequence syntax in the sample code if it is supported. -* All examples should be formatted to be included in `configuration.yaml` unless explicitly stated. - * Use capital letters and `_` to indicate that the value needs to be replaced. E.g., `api_key: YOUR_API_KEY` or `api_key: REPLACE_ME`. - * If you know that the API key or value contains [control characters](https://en.wikipedia.org/wiki/YAML#Syntax), e.g., `#`, `[`, `?`, etc., wrap it in quotes and add a note. -* Integration and platform names should be a link to their respective documentation pages. - -Example configuration block - -```yaml -{% configuration %} -some_key: - description: This is a description of what this key is for. - required: false - type: string - default: Optional default value - leave out if there isn't one -{% endconfiguration %} -``` - -## Templates - -* All examples containing Jinja2 templates should be wrapped **outside** of the code markdown with the `{% raw %}` tag. -* Do not use `states.switch.source.state` in templates. Instead use `states()` and `is_state()`. -* Use double quotes (`"`) for ([more information](#single-vs-double-quotation-marks)): - * `friendly_name` - * Single-line templates: - * `value_template` - * `level_template` - * `icon_template` - * Children of `data_template` -* Use single quotes (`'`) for ([more information](#single-vs-double-quotation-marks): - * Strings inside of templates: - * States - * Entity IDs - * `unit_of_measurement` -* No whitespace around pipe character (`|`) for Jinja2 filters. -* Single whitespace after Jinja2 opening delimiters ({% raw %}`{{`{% endraw %}). -* Single whitespace before Jinja2 closing delimiters ({% raw %}`}}`{% endraw %}). -* Do not quote values for: - * `device_class` - * `platform` - * `condition` - * `service` - -## Renaming Pages - -It can happen that a integration or platform is renamed, in this case the documentation needs to be updated as well. If you rename a page, add `redirect_from:` to the file header and let it point to the old location/name of the page. Please consider to add details, like release number or old integration/platform name, to the page in a [note](/developers/documentation/create_page/#html). - -```text ---- -... -redirect_from: /getting-started/android/ ---- -``` - -Adding a redirect also applies if you move content around in the [documentation](/docs/). - -## Single vs. Double Quotation Marks - -Use single quotes (`'`) for strings inside of a template. It is more obvious to escape a single quote when necessary (i.e. `name` is a possessive noun), because the single quotes that wrap the string are closer in position to the apostrophe inside the string. Use double quotes (`"`) outside of a template (unless it is a multi-line template, in which case outside quotes are not required). - -### Examples - -#### Double Quotes Outside, Single Quotes Inside (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: "{% if trigger.to_state.name == 'Dale\'s Bedroom' %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}" -``` - -#### Single Quotes Outside, Double Quotes Inside (Invalid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: '{% if trigger.to_state.name == "Dale's Bedroom" %}Someone's in your base, killing your noobs!{% else %}It's just another door.{% endif %}' -``` - -#### Multi-Line Template (Valid) - -```yaml -automation: - ... - action: - - service: notify.notify - data_template: - message: >- - {% if trigger.to_state.name == 'Dale\'s Bedroom' %} - Someone's in your base, killing your noobs! - {% else %} - It's just another door. - {% endif %} -``` diff --git a/website/versioned_docs/version-0.96.0/entity_climate.md b/website/versioned_docs/version-0.96.0/entity_climate.md deleted file mode 100644 index 12eb33dd..00000000 --- a/website/versioned_docs/version-0.96.0/entity_climate.md +++ /dev/null @@ -1,221 +0,0 @@ ---- -title: Climate Entity -sidebar_label: Climate -id: version-0.96.0-entity_climate -original_id: entity_climate ---- - -A climate entity is a device that controls temperature, humidity, or fans, such as A/C systems and humidifiers. Derive entity platforms from [`homeassistant.components.climate.ClimateDevice`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/components/climate/__init__.py) - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description | -| ----------------------- | ------ | ------------------------------------ | ------------------------------------------------------------------------------------------------------------ | -| temperature_unit | string | `NotImplementedError` | The unit of temperature measurement for the system (`TEMP_CELSIUS` or `TEMP_FAHRENHEIT`). | -| precision | float | Based on `temperature_unit` | The precision of the temperature in the system. Defaults to tenths for TEMP_CELSIUS, whole number otherwise. | -| current_temperature | float | None | The current temperature. | -| current_humidity | float | None | The current humidity. | -| target_temperature | float | None | The temperature currently set to be reached. | -| target_temperature_high | float | None | The upper bound target temperature | -| target_temperature_low | float | None | The lower bound target temperature | -| target_temperature_step | float | None | The supported step size a target temperature can be increased/decreased | -| target_humidity | float | None | The target humidity the device is trying to reach. Requires `SUPPORT_TARGET_HUMIDITY`. | -| max_temp | int | `DEFAULT_MAX_TEMP` (value == 35) | Returns the maximum temperature. | -| min_temp | int | `DEFAULT_MIN_TEMP` (value == 7) | Returns the minimum temperature. | -| max_humidity | int | `DEFAULT_MAX_HUMIDITY` (value == 99) | Returns the maximum humidity. Requires `SUPPORT_TARGET_HUMIDITY`. | -| min_humidity | int | `DEFAULT_MIN_HUMIDITY` (value == 30) | Returns the minimum humidity. Requires `SUPPORT_TARGET_HUMIDITY`. | -| hvac_mode | string | `NotImplementedError()` | The current operation (e.g. heat, cool, idle). Used to determine `state`. | -| hvac_action | string | None | The current HVAC action (heating, cooling) | -| hvac_modes | list | `NotImplementedError()` | List of available operation modes. See below. | -| preset_mode | string | `NotImplementedError()` | The current active preset. Requires `SUPPORT_PRESET_MODE`. | -| preset_modes | list | `NotImplementedError()` | The available presets. Requires `SUPPORT_PRESET_MODE`. | -| fan_mode | string | `NotImplementedError()` | Returns the current fan mode. Requires `SUPPORT_FAN_MODE`. | -| fan_modes | list | `NotImplementedError()` | Returns the list of available fan modes. Requires `SUPPORT_FAN_MODE`. | -| swing_mode | string | `NotImplementedError()` | Returns the fan setting. | -| swing_modes | list | `NotImplementedError()` | Returns the list of available swing modes. | -| is_aux_heat | bool | None | Returns True if an auxiliary heater is on. Requires `SUPPORT_AUX_HEAT`. | -| supported_features | int | `NotImplementedError()` | Bitmap of supported features. See below. | - -### HVAC modes - -You are only allowed to use the built-in HVAC modes. If you want another mode, add a preset instead. - -| Name | Description | -| --------------------- | ------------------------------------------------------------------- | -| `HVAC_MODE_OFF` | The device is turned off. | -| `HVAC_MODE_HEAT` | The device is set to heat to a target temperature. | -| `HVAC_MODE_COOL` | The device is set to cool to a target temperature. | -| `HVAC_MODE_HEAT_COOL` | The device supports heating/cooling to a range | -| `HVAC_MODE_AUTO` | The device is set to a schedule, learned behavior, AI. | -| `HVAC_MODE_DRY` | The device is set to dry/humidity mode. | -| `HVAC_MODE_FAN_ONLY` | The device only has the fan on. No heating or cooling taking place. | - -### HVAC Action - -The HVAC action describes the _current_ action. This is different from the mode, because if a device is set to heat, and the target temperature is already achieved, the device will not be actively heating anymore. - -| Name | Description | -| ------------------- | --------------------- | -| `CURRENT_HVAC_OFF` | Device is turned off. | -| `CURRENT_HVAC_HEAT` | Device is heating. | -| `CURRENT_HVAC_COOL` | Device is cooling. | -| `CURRENT_HVAC_DRY` | Device is dring. | -| `CURRENT_HVAC_IDLE` | Device is idle. | - -### Presets - -A device can have different presets that it might want to show to the user. Common presets are "Away" or "Eco". There are a couple of built-in presets that will offer translations, but you're also allowed to add custom presets. - -| Name | Description | -| ---------- | ------------------------------------------------------ | -| `ECO` | Device is running an energy-saving mode | -| `AWAY` | Device is in away mode | -| `BOOST` | Device turn all valve full up | -| `COMFORT` | Device is in comfort mode | -| `HOME` | Device is in home mode | -| `SLEEP` | Device is prepared for sleep | -| `ACTIVITY` | Device is reacting to activity (e.g. movement sensors) | - -### Fan modes - -A device's fan can have different states. There are a couple of built-in fan modes, but you're also allowed to use custom fan modes. - -| Name | -| ------------- | -| `FAN_ON` | -| `FAN_OFF` | -| `FAN_AUTO` | -| `FAN_LOW` | -| `FAN_MEDIUM` | -| `FAN_HIGH` | -| `FAN_MIDDLE` | -| `FAN_FOCUS` | -| `FAN_DIFFUSE` | - -### Swing modes - -The device fan can have different swing modes that it wants the user to know about/control. - -| Name | Description | -| ------------------ | ------------------------------------------------ | -| `SWING_OFF` | The fan is not swinging. | -| `SWING_VERTICAL` | The fan is swinging vertical. | -| `SWING_HORIZONTAL` | The fan is swinging horizontal. | -| `SWING_BOTH` | The fan is swingin both horizontal and vertical. | - -### Supported features - -Supported features constants are combined using the bitwise or (`|`) operator. - -| Name | Description | -| ---------------------------------- | ------------------------------------------------------------------------------------------- | -| `SUPPORT_TARGET_TEMPERATURE` | The device supports a target temperature. | -| `SUPPORT_TARGET_TEMPERATURE_RANGE` | The device supports a ranged target temperature. Used for HVAC modes `heat_cool` and `auto` | -| `SUPPORT_TARGET_HUMIDITY` | The device supports a target humidity. | -| `SUPPORT_FAN_MODE` | The device supports fan modes. | -| `SUPPORT_PRESET_MODE` | The device supports presets. | -| `SUPPORT_SWING_MODE` | The device supports swing modes. | -| `SUPPORT_AUX_HEAT` | The device supports auxiliary heaters. | - -## Methods - -### Set hvac mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_hvac_mode(self, hvac_mode): - """Set new target hvac mode.""" - - async def async_set_hvac_mode(self, hvac_mode): - """Set new target hvac mode.""" -``` - -### Set preset mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_preset_mode(self, preset_mode): - """Set new target preset mode.""" - - async def async_set_preset_mode(self, preset_mode): - """Set new target preset mode.""" -``` - -### Set fan mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_fan_mode(self, fan_mode): - """Set new target fan mode.""" - - async def async_set_fan_mode(self, fan_mode): - """Set new target fan mode.""" -``` - -### Set humidity - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_humidity(self, humidity): - """Set new target humidity.""" - - async def async_set_humidity(self, humidity): - """Set new target humidity.""" -``` - -### Set swing mode - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_swing_mode(self, swing_mode): - """Set new target swing operation.""" - - async def async_set_swing_mode(self, swing_mode): - """Set new target swing operation.""" -``` - -### Set temperature - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def set_temperature(self, **kwargs): - """Set new target temperature.""" - - async def async_set_temperature(self, **kwargs): - """Set new target temperature.""" -``` - -### Control auxiliary heater - -```python -class MyClimateDevice(ClimateDevice): - # Implement one of these methods. - - def turn_aux_heat_on(self): - """Turn auxiliary heater on.""" - - async def async_turn_aux_heat_on(self): - """Turn auxiliary heater on.""" - - # Implement one of these methods. - - def turn_aux_heat_off(self): - """Turn auxiliary heater off.""" - - async def async_turn_aux_heat_off(self): - """Turn auxiliary heater off.""" -``` diff --git a/website/versioned_docs/version-0.96.0/hassio_addon_config.md b/website/versioned_docs/version-0.96.0/hassio_addon_config.md deleted file mode 100644 index 007b7486..00000000 --- a/website/versioned_docs/version-0.96.0/hassio_addon_config.md +++ /dev/null @@ -1,228 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.96.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - apparmor.txt - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -All our Images have also [bashio][bashio] installed. It contains a set of commonly used operations and can be used to be included in add-ons to reduce code duplication across add-ons and therefore making it easier to develop and maintain add-ons. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use bashio or `jq` inside your shell script to parse this data. - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -[bashio]: https://github.com/hassio-addons/bashio - -## Add-on Docker file - -All add-ons are based on latest Alpine Linux. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | yes | List of supported arch: `armhf`, `armv7`, `aarch64`, `amd64`, `i386`. -| machine | list | no | Default it support any machine type. You can select that this add-on run only on specific machines. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| homeassistant | string | no | Pin a minimum required Home Assistant version for such Add-on. Value is a version string like `0.91.2`. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| kernel_modules | bool | no | Map host kernel modules and config into add-on (readonly). -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| auth_api | bool | no | Allow access to Home Assistent user backend. -| ingress | bool | no | Enable the ingress feature for the Add-on -| ingress_port | integer | no | Default `8099`. For Add-ons they run on host network, you can use `0` and read the port later on API. -| ingress_entry | string | no | Modify the URL entry point from `/`. -| panel_icon | string | no | Default: mdi:puzzle. MDI icon for the menu panel integration. -| panel_title | string | no | Default add-on name, but can Modify with this options. -| panel_admin | bool | no | Default True. Make menu entry only available with admin privileged. - - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. - -We provide a set of [Base-Images][hassio-base] which should cover a lot of needs. If you don't want use the Alpine based version or need a specific Image tag, feel free to pin this requirements for you build with `build_from` option. - -[hassio-base]: https://github.com/home-assistant/hassio-base diff --git a/website/versioned_docs/version-0.97.0/creating_integration_manifest.md b/website/versioned_docs/version-0.97.0/creating_integration_manifest.md deleted file mode 100644 index f2730b71..00000000 --- a/website/versioned_docs/version-0.97.0/creating_integration_manifest.md +++ /dev/null @@ -1,137 +0,0 @@ ---- -title: Integration Manifest -sidebar_label: Manifest -id: version-0.97.0-creating_integration_manifest -original_id: creating_integration_manifest ---- - -Since 0.92.0, every integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, except for custom components. - -```json -{ - "domain": "hue", - "name": "Philips Hue", - "documentation": "https://www.home-assistant.io/components/hue", - "dependencies": ["mqtt"], - "codeowners": ["@balloob"], - "requirements": ["aiohue==1.9.1"] -} -``` - -Or a minimal example that you can copy into your project: - -```json -{ - "domain": "your_domain_name", - "name": "Your Integration", - "documentation": "https://www.example.com", - "dependencies": [], - "codeowners": [], - "requirements": [] -} -``` - -## Domain - -The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`. - -## Name - -The name of the integration. - -## Documentation - -The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/` - -## Dependencies - -Dependencies are other Home Assistant integrations that you want Home Assistant to set up successfully prior to the integration being loaded. This can be necessary in case you want to offer functionality from that other integration, like using webhooks or an MQTT connection. - -## Code Owners - -GitHub usernames or team names of people that are responsible for this integration. You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included. - -## Config Flow - -Specify the `config_flow` key if your integration has a config flow to create a config entry. When specified, the file `config_flow.py` needs to exist in your integration. - -```json5 -{ - "config_flow": true -} -``` - -## Requirements - -Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you are running in a virtual environment. This will make sure that all requirements are present at startup. If steps fail, like missing packages for the compilation of a module or other install errors, the component will fail to load. - -Requirements is an array of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v3.2.0: `["pychromecast==3.2.0"]`. - -### Custom requirements during development & testing - -During the development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using `pychromecast` as an example: - -```bash -pip install pychromecast==3.2.0 --target ~/.homeassistant/deps -hass --skip-pip -``` - -This will use the specified version, and prevent Home Assistant from trying to override it with what is specified in `requirements`. - -If you need to make changes to a requirement to support your component, it's also possible to install a development version of the requirement using `pip install -e`: - -```bash -git clone https://github.com/balloob/pychromecast.git -pip install -e ./pychromecast -hass --skip-pip -``` - -## Zeroconf - -If your integration supports discovery via [Zeroconf](https://en.wikipedia.org/wiki/Zero-configuration_networking), you can add the type to your manifest. If the user has the `zeroconf` integration loaded, it will load the `zeroconf` step of your integration's config flow when it is discovered. - -```json5 -{ - "zeroconf": ["_googlecast._tcp.local."] -} -``` - -## SSDP - -If your integration supports discovery via [SSDP](https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol), you can add the type to your manifest. If the user has the `ssdp` integration loaded, it will load the `ssdp` step of your integration's config flow when it is discovered. We support SSDP discovery by ST, manufacturer and device type. Your integration is discovered if any of the specified info is found. It's up to your config flow to filter out duplicates. - -```json5 -{ - "ssdp": { - "st": [ - "roku:ecp" - ], - "manufacturer": [ - "Roku" - ], - "device_type": [ - "urn:roku-com:device:player:1-0" - ] - } -} -``` - -## HomeKit - -If your integration supports discovery via HomeKit, you can add the supported model names to your manifest. If the user has the `zeroconf` integration loaded, it will load the `homekit` step of your integration's config flow when it is discovered. - -HomeKit discovery works by testing if the discovered modelname starts with any of the model names specified in the manifest.json. - -```json5 -{ - "homekit": { - "models": [ - "LIFX" - ] - } -} -``` - -Discovery via HomeKit does not mean that you have to talk the HomeKit protocol to communicate with your device. You can communicate with the device however you see fit. - -When a discovery info is routed to your integration because of this entry in your manifest, the discovery info is no longer routed to integrations that listen to the HomeKit zeroconf type. diff --git a/website/versioned_docs/version-0.97.0/external_api_websocket.md b/website/versioned_docs/version-0.97.0/external_api_websocket.md deleted file mode 100644 index e0868866..00000000 --- a/website/versioned_docs/version-0.97.0/external_api_websocket.md +++ /dev/null @@ -1,437 +0,0 @@ ---- -title: WebSocket API -id: version-0.97.0-external_api_websocket -original_id: external_api_websocket ---- - -Home Assistant contains a WebSocket API. This API can be used to stream information from a Home Assistant instance to any client that implements WebSockets. Implementations in different languages: - -- [JavaScript](https://github.com/home-assistant/home-assistant-js-websocket) - powers the frontend -- [Python](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket-client.py) - CLI client using [`asyncws`](https://async-websockets.readthedocs.io/en/latest/) -- [JavaScript/HTML](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket.html) - WebSocket connection in your browser - -Connect your websocket implementation to `ws://localhost:8123/api/websocket`. You will need a valid access token. - -If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`websocket_api` component](https://www.home-assistant.io/components/websocket_api/) to your `configuration.yaml` file to use the WebSocket API. - -## Server states - -1. Client connects. -1. Authentication phase starts. - - Server sends `auth_required` message. - - Client sends `auth` message. - - If `auth` message correct: go to 3. - - Server sends `auth_invalid`. Go to 6. -1. Send `auth_ok` message -1. Authentication phase ends. -1. Command phase starts. - 1. Client can send commands. - 1. Server can send results of previous commands. -1. Client or server disconnects session. - -During the command phase, the client attaches a unique identifier to each message. The server will add this identifier to each message so that the client can link each message to its origin. - -## Message format - -Each API message is a JSON serialized object containing a `type` key. After the authentication phase messages also must contain an `id`, an integer that contains the number of interactions. - -Example of an auth message: - -```json -{ - "type": "auth", - "access_token": "ABCDEFGHIJKLMNOPQ" -} -``` - -```json -{ - "id": 5, - "type":"event", - "event":{ - "data":{}, - "event_type":"test_event", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -## Authentication phase - -When a client connects to the server, the server will test if the client is authenticated. Authentication will not be necessary if no api_password is set or if the user fulfills one of the other criteria for authentication (trusted network, password in url/header). - -If no authentication is needed, the authentication phase will complete and the server will send an `auth_ok` message. - -```json -{ - "type": "auth_ok" -} -``` - -If authentication is necessary, the server sends out `auth_required`. - -```json -{ - "type": "auth_required" -} -``` - -This means that the next message from the client should be an auth message. You can authorize with an access token. - -```json -{ - "type": "auth", - "access_token": "ABCDEFGH" -} -``` - -For now, we also support authentication with an API password (legacy auth). - -```json -{ - "type": "auth", - "api_password": "supersecret" -} -``` - -If the client supplies valid authentication, the authentication phase will complete by the server sending the `auth_ok` message: - -```json -{ - "type": "auth_ok" -} -``` - -If the data is incorrect, the server will reply with `auth_invalid` message and disconnect the session. - -```json -{ - "type": "auth_invalid", - "message": "Invalid password" -} -``` - -## Command phase - -During this phase the client can give commands to the server. The server will respond to each command with a `result` message indicating when the command is done and if it was successful. - -```json -{ - "id": 6, - "type": "result", - "success": true, - // Can contain extra result info - "result": null -} -``` - -## Subscribe to events - -The command `subscribe_events` will subscribe your client to the event bus. You can either listen to all events or to a specific event type. If you want to listen to multiple event types, you will have to send multiple `subscribe_events` commands. - -```json -{ - "id": 18, - "type": "subscribe_events", - // Optional - "event_type": "state_changed" -} -``` - -The server will respond with a result message to indicate that the subscription is active. - -```json -{ - "id": 18, - "type": "result", - "success": true, - "result": null -} -``` - -For each event that matches, the server will send a message of type `event`. The `id` in the message will point at the original `id` of the `listen_event` command. - -```json -{ - "id": 18, - "type":"event", - "event":{ - "data":{ - "entity_id":"light.bed_light", - "new_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:24.265390+00:00", - "state":"on", - "attributes":{ - "rgb_color":[ - 254, - 208, - 0 - ], - "color_temp":380, - "supported_features":147, - "xy_color":[ - 0.5, - 0.5 - ], - "brightness":180, - "white_value":200, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:24.265390+00:00" - }, - "old_state":{ - "entity_id":"light.bed_light", - "last_changed":"2016-11-26T01:37:10.466994+00:00", - "state":"off", - "attributes":{ - "supported_features":147, - "friendly_name":"Bed Light" - }, - "last_updated":"2016-11-26T01:37:10.466994+00:00" - } - }, - "event_type":"state_changed", - "time_fired":"2016-11-26T01:37:24.265429+00:00", - "origin":"LOCAL" - } -} -``` - -### Unsubscribing from events - -You can unsubscribe from previously created subscription events. Pass the id of the original subscription command as value to the subscription field. - -```json -{ - "id": 19, - "type": "unsubscribe_events", - "subscription": 18 -} -``` - -The server will respond with a result message to indicate that unsubscribing was successful. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": null -} -``` - -## Calling a service - -This will call a service in Home Assistant. Right now there is no return value. The client can listen to `state_changed` events if it is interested in changed entities as a result of a service call. - -```json -{ - "id": 24, - "type": "call_service", - "domain": "light", - "service": "turn_on", - // Optional - "service_data": { - "entity_id": "light.kitchen" - } -} -``` - -The server will indicate with a message indicating that the service is done executing. - -```json -{ - "id": 24, - "type": "result", - "success": true, - "result": null -} -``` - -## Fetching states - -This will get a dump of all the current states in Home Assistant. - -```json -{ - "id": 19, - "type": "get_states" -} -``` - -The server will respond with a result message containing the states. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -## Fetching config - -This will get a dump of the current config in Home Assistant. - -```json -{ - "id": 19, - "type": "get_config" -} -``` - -The server will respond with a result message containing the config. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -## Fetching services - -This will get a dump of the current services in Home Assistant. - -```json -{ - "id": 19, - "type": "get_services" -} -``` - -The server will respond with a result message containing the services. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { ... } -} -``` - -## Fetching panels - -This will get a dump of the current registered panels in Home Assistant. - -```json -{ - "id": 19, - "type": "get_panels" -} -``` - -The server will respond with a result message containing the current registered panels. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": [ ... ] -} -``` - -## Fetching camera thumbnails - -_Introduced in Home Assistant 0.69._ - -Return a b64 encoded thumbnail of a camera entity. - -```json -{ - "id": 19, - "type": "camera_thumbnail", - "entity_id": "camera.driveway" -} -``` - -The server will respond with a result message containing the thumbnail. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Fetching media player thumbnails - -_Introduced in Home Assistant 0.69._ - -Fetch a base64 encoded thumbnail picture for a media player. - -```json -{ - "id": 19, - "type": "media_player_thumbnail", - "entity_id": "media_player.living_room" -} -``` - -The server will respond with the image encoded via base64. - -```json -{ - "id": 19, - "type": "result", - "success": true, - "result": { - "content_type": "image/jpeg", - "content": "" - } -} -``` - -## Pings and Pongs - -The API supports receiving a ping from the client and returning a pong. This serves as a heartbeat to ensure the connection is still alive: - -```json -{ - "id": 19, - "type": "ping" -} -``` - -The server must send a pong back as quickly as possible, if the connection is still active: - -```json -{ - "id": 19, - "type": "pong" -} -``` - -## Error handling - -If an error occurs, the `success` key in the `result` message will be set to `false`. It will contain an `error` key containing an object with two keys: `code` and `message`. - -| Code | Description | -| ----- | ------------ | -| 1 | A non-increasing identifier has been supplied. -| 2 | Received message is not in expected format (voluptuous validation error). -| 3 | Requested item cannot be found - -```json -{ - "id": 12, - "type":"result", - "success": false, - "error": { - "code": 2, - "message": "Message incorrectly formatted: expected str for dictionary value @ data['event_type']. Got 100" - } -} -``` diff --git a/website/versioned_docs/version-0.98.0/config_entries_config_flow_handler.md b/website/versioned_docs/version-0.98.0/config_entries_config_flow_handler.md deleted file mode 100644 index cb4dcc2e..00000000 --- a/website/versioned_docs/version-0.98.0/config_entries_config_flow_handler.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -title: Integration Configuration -sidebar_label: Configuration -id: version-0.98.0-config_entries_config_flow_handler -original_id: config_entries_config_flow_handler ---- - -Integrations can be set up via the user interface by adding support for a config config to create a config entry. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like Hass.io). - -Config Flow Handlers control the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes. - -When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component. - -## Updating the manifest - -You need to update your integrations manifest to inform Home Assistant that your integration has a config flow. This is done by adding `config_flow: true` to your manifest ([docs](creating_integration_manifest.md#config-flow)). - -## Defining your config flow - -Config entries uses the [data flow entry framework](data_entry_flow_index.md) to define their config flows. The config flow needs to be defined in the file `config_flow.py` in your integration folder, extend `homeassistant.config_entries.ConfigFlow` and pass a `domain` key as part of inheriting `ConfigFlow`. - -```python -from homeassistant import config_entries -from .const import DOMAIN - -class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): -``` - -## Defining steps - -Your config flow will need to define steps of your configuration flow. The docs for [Data Entry Flow](data_entry_flow_index.md) describe the different return values of a step. Here is an example on how to define the `user` step. - -```python -class ExampleConfigFlow(config_entries.ConfigFlow, domain=DOMAIN): - - async def async_step_user(self, info): - if info is not None: - # process info - - return self.async_show_form( - step_id='user', - data_schema=vol.Schema({ - vol.Required('password'): str - }) - ) -``` - -There are a few step names reserved for system use: - -| Step name | Description | -| ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `user` | Invoked when a user initiates a flow via the user interface. | -| `zeroconf` | Invoked if your integration has been discovered via Zeroconf/mDNS as specified [using `zeroconf` in the manifest](creating_integration_manifest.md#zeroconf). | -| `homekit` | Invoked if your integration has been discovered via HomeKit as specified [using `homekit` in the manifest](creating_integration_manifest.md#homekit). | -| `ssdp` | Invoked if your integration has been discovered via SSDP/uPnP as specified [using `ssdp` in the manifest](creating_integration_manifest.md#ssdp). | -| `discovery` | _DEPRECATED_ Invoked if your integration has been discovered by the discovery integration. | - -## Discovery steps - -When an integration is discovered, their respective discovery step is invoked with the discovery information. The step will have to check the following things: - -- Make sure there are no other instances of this config flow in progress of setting up the discovered device. This can happen if there are multiple ways of discovering that a device is on the network. -- Make sure that the device is not already set up. -- Invoking a discovery step should never result in a finished flow and a config entry. Always confirm with the user. - -## Discoverable integrations that require no authentication - -If your integration is discoverable without requiring any authentication, you'll be able to use the Discoverable Flow that is built-in. This flow offers the following features: - -- Detect if devices/services can be discovered on the network before finishing the config flow. -- Support all manifest-based discovery protocols. -- Limit to only 1 config entry. It is up to the config entry to discover all available devices. - -```python -"""Config flow for LIFX.""" -from homeassistant.helpers import config_entry_flow -from homeassistant import config_entries - -import aiolifx - -from .const import DOMAIN - - -async def _async_has_devices(hass): - """Return if there are devices that can be discovered.""" - lifx_ip_addresses = await aiolifx.LifxScan(hass.loop).scan() - return len(lifx_ip_addresses) > 0 - - -config_entry_flow.register_discovery_flow( - # Domain of your integration - DOMAIN, - # Title of the created config entry - 'LIFX', - # async method that returns a boolean if devices/services are found - _async_has_devices, - # Connection class of the integration - config_entries.CONN_CLASS_LOCAL_POLL -) -``` - -## Translations - -Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component: - -```json -{ - "config": { - "title": "Philips Hue Bridge", - "step": { - "init": { - "title": "Pick Hue bridge", - "data": { - "host": "Host" - } - }, - "link": { - "title": "Link Hub", - "description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n![Location of button on bridge](/static/images/config_philips_hue.jpg)" - } - }, - "error": { - "register_failed": "Failed to register, please try again", - "linking": "Unknown linking error occurred." - }, - "abort": { - "discover_timeout": "Unable to discover Hue bridges", - "no_bridges": "No Philips Hue bridges discovered", - "all_configured": "All Philips Hue bridges are already configured", - "unknown": "Unknown error occurred", - "cannot_connect": "Unable to connect to the bridge", - "already_configured": "Bridge is already configured" - } - } -} -``` - -When the translations are merged into Home Assistant, they will be automatically uploaded to [Lokalise](https://lokalise.co/) where the translation team will help to translate them in other languages. [More info on translating Home Assistant.](internationalization_translation.md) diff --git a/website/versioned_docs/version-0.98.0/config_entries_options_flow_handler.md b/website/versioned_docs/version-0.98.0/config_entries_options_flow_handler.md deleted file mode 100644 index c96b3cc1..00000000 --- a/website/versioned_docs/version-0.98.0/config_entries_options_flow_handler.md +++ /dev/null @@ -1,60 +0,0 @@ ---- -title: Integration Configuration Options -sidebar_label: Configuration Options -id: version-0.98.0-config_entries_options_flow_handler -original_id: config_entries_options_flow_handler ---- - -An integration that is configured via a config entry can expose options to the user to allow tweaking behavior of the integration, like which devices or locations should be integrated. - -Config Entry Options uses the [Data Flow Entry framework](data_entry_flow_index.md) to allow users to update a config entries options. Components that want to support config entry options will need to define a Options Flow Handler. - -## Options support - -For an integration to support options it needs to have an `async_get_options_flow` method in its config flow handler. Calling it will return an instance of the components options flow handler. - -```python -@staticmethod -@callback -def async_get_options_flow(config_entry): - return OptionsFlowHandler() -``` - -## Flow handler - -The Flow handler works just like the config flow handler, except that the first step in the flow will always be `async_step_init`. - -```python -class OptionsFlowHandler(config_entries.OptionsFlow): - - async def async_step_init(self, user_input=None): - """Manage the options.""" - if user_input is not None: - return self.async_create_entry(title="", data=user_input) - - return self.async_show_form( - step_id="init", - data_schema=vol.Schema( - { - vol.Required( - "show_things", - default=self.config_entry.options.get("show_things"), - ): bool - } - ), - ) -``` - -## Signal updates - -If the component should act on updated options, you can register an update listener to the config entry that will be called when the entry is updated. - -```python -entry.add_update_listener(update_listener) -``` - -The Listener shall be an async function that takes the same input as async_setup_entry. Options can then be accessed from `entry.options`. - -```python -async def update_listener(hass, entry): -``` diff --git a/website/versioned_docs/version-0.98.0/creating_component_generic_discovery.md b/website/versioned_docs/version-0.98.0/creating_component_generic_discovery.md deleted file mode 100644 index 6e387fa0..00000000 --- a/website/versioned_docs/version-0.98.0/creating_component_generic_discovery.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: Integration with Multiple Platforms -sidebar_label: Multiple platforms -id: version-0.98.0-creating_component_generic_discovery -original_id: creating_component_generic_discovery ---- - -Most integrations consist of a single platform. And in that case, it's fine to just define that one platform. However, if you are going to add a second platform, you will want to centralize your connection logic. This is done inside the component (`__init__.py`). - -If your integration is configurable via `configuration.yaml`, it will cause the entry point of your configuration to change, as now users will need to set up your integration directly, and it is up to your integration to set up the platforms. - -## Loading platforms when configured via a config entry - -If your integration is set up via a config entry, you will need to forward the config entry to the appropriate integration to set up your platform. For more info, see the [config entry documentation](config_entries_index.md#for-platforms). - -## Loading platforms when configured via configuration.yaml - -If your integration is not using config entries, it will have to use our discovery helpers to set up its platforms. Note, this approach does not support unloading. - -To do this, you will need to use the `load_platform` and `async_load_platform` methods from the discovery helper. - - -- See also a [full example that implements this logic](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/example_load_platform/) diff --git a/website/versioned_docs/version-0.98.0/development_environment.md b/website/versioned_docs/version-0.98.0/development_environment.md deleted file mode 100644 index d420f6a8..00000000 --- a/website/versioned_docs/version-0.98.0/development_environment.md +++ /dev/null @@ -1,147 +0,0 @@ ---- -title: Set up Development Environment -id: version-0.98.0-development_environment -original_id: development_environment ---- - -You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up. - -## Preparing your environment - -### Developing on Linux - -Install the core dependencies. - -```bash -$ sudo apt-get install python3-pip python3-dev python3-venv -``` - -In order to run `script/setup` below you will need some more dependencies. - -```bash -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev pkg-config -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -> Different distributions have different package installation mechanisms and sometimes packages names as well. For example CentOS would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc` - -Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more. - -### Developing on Windows - -Due to Home Assistant is mainly designed and developed on Linux distributions, on Windows 10 you can setup a [Linux subsystem](https://docs.microsoft.com/windows/wsl/install-win10). - -Open Powershell as an Administrator and run - -```bash -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux -``` - -From Windows Store install Ubuntu. - -When the Linux subsystem is set up, perform install as for Linux. - -```bash -$ sudo apt-get update -$ sudo apt-get install python3-pip python3-dev python3-venv -$ sudo apt-get install autoconf libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev -$ sudo apt-get install -y libavformat-dev libavcodec-dev libavdevice-dev libavutil-dev libswscale-dev libavresample-dev libavfilter-dev -``` - -Hint: Git is included in Linux subsytem. - -When invoking your installation (see below), make sure to specify a folder for configuration which is accessible from Windows. - -```bash -$ mkdir -p ../config -$ hass -c ../config -``` - -### Developing on macOS - -Install [Homebrew](https://brew.sh/), then use that to install Python 3: - -```bash -$ brew install python3 autoconf -``` - -Then install ffmpeg: - -```bash -$ brew install ffmpeg -``` - -### Developing with devcontainer - -The devcontainer is a preconfigured development environment with all the tools you need. - -**Prerequisites** - -- [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) -- [Docker](https://docs.docker.com/install/) -- [Visual Studio code](https://code.visualstudio.com/) -- [Remote - Containers (VSC Extension)](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.remote-containers) - -[More info about requirements and devcontainer in general](https://code.visualstudio.com/docs/remote/containers#_getting-started) - -**Getting started:** - -1. Fork the repository. -1. Clone the repository to your computer. -1. Open the repository using Visual Studio code. - -When you open this repository with Visual Studio code you are asked to "Reopen in Container", this will start the build of the container. - -_If you don't see this notification, open the command pallet and select `Remote-Containers: Reopen Folder in Container`._ - -The devcontainter comes with some useful tasks to help you with development, you can start these tasks by opening the command pallet and select `Tasks: Run Task` then select the task you want to run. - -Running tasks like `Preview` can be restarted by opening the command pallet and selecting `Tasks: Restart Running Task`, then select the task you want to restart. - -## Setup Local Repository - -Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**. -Once forked, setup your local copy of the source using the commands: - -```bash -$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git -$ cd home-assistant -$ git remote add upstream https://github.com/home-assistant/home-assistant.git -``` - -## Setting up virtual environment - -To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment. - -```bash -$ python3 -m venv venv -$ source venv/bin/activate -``` - -Install the requirements with a provided script named `setup`. - -```bash -$ script/setup -``` - -Invoke your installation, adjusting the [configuration](https://www.home-assistant.io/docs/configuration/) if required. - -```bash -$ hass -``` - -## Logging - -By default logging in Home Assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels). - -You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on: - -```yaml -logger: - default: info - logs: - homeassistant.core: debug - nest.nest: debug - asyncio: debug - homeassistant.components.cloud.iot: debug -``` diff --git a/website/versioned_docs/version-0.98.0/development_guidelines.md b/website/versioned_docs/version-0.98.0/development_guidelines.md deleted file mode 100644 index 47ec95f2..00000000 --- a/website/versioned_docs/version-0.98.0/development_guidelines.md +++ /dev/null @@ -1,71 +0,0 @@ ---- -title: Style guidelines -id: version-0.98.0-development_guidelines -original_id: development_guidelines ---- - -Home Assistant enforces quite strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. - -We use [Black](https://github.com/psf/black) for uncompromised code formatting. Every pull request is automatically checked as part of the linting process and we never merge submissions that diverge. - -Summary of the most relevant points: - -- Comments should be full sentences and end with a period. -- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered. -- Constants and the content of lists and dictionaries should be in alphabetical order. - -It is advisable to adjust IDE or editor settings to match those requirements. - -## Our recommendations - -For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code consistent. - -### File headers - -The docstring in the file header should describe what the file is about. - -```python -"""Support for MQTT lights.""" -``` - -### Log messages - -There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. A widely used style is shown below but you are free to compose the messages as you like. - -```python -_LOGGER.error("No route to device: %s", self._resource) -``` - -```bash -2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18 -``` - -Do not print out API keys, tokens, usernames or passwords (even if they are wrong). -Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` for anything else. - -### Ordering of imports - -Instead of order the imports manually, use [`isort`](https://github.com/timothycrosley/isort). - -```bash -$ pip3 install isort -$ isort homeassistant/components/sensor/fixer.py -``` - -### Use new style string formatting - -Prefer [f-strings](https://docs.python.org/3/reference/lexical_analysis.html#f-strings) over `%` or `str.format`. - -```python -# New -f"{some_value} {some_other_value}" -# Old, wrong -"{} {}".format('New', 'style') -"%s %s" % ('Old', 'style') -``` - -One exception is for logging which uses the percentage formatting. This is to avoid formatting the log message when it is suppressed. - -```python -_LOGGER.info("Can't connect to the webservice %s at %s", string1, string2) -``` diff --git a/website/versioned_docs/version-0.98.0/entity_index.md b/website/versioned_docs/version-0.98.0/entity_index.md deleted file mode 100644 index d40c05bf..00000000 --- a/website/versioned_docs/version-0.98.0/entity_index.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Entity -sidebar_label: Introduction -id: version-0.98.0-entity_index -original_id: entity_index ---- - -Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating. - -Below is an example switch entity that keeps track of their state in memory. - -```python -from homeassistant.components.switch import SwitchDevice - -class MySwitch(SwitchDevice): - - def __init__(self): - self._is_on = False - - @property - def name(self): - """Name of the device.""" - return 'My Switch' - - @property - def is_on(self): - """If the switch is currently on or off.""" - return self._is_on - - def turn_on(self, **kwargs): - """Turn the switch on.""" - self._is_on = True - - def turn_off(self, **kwargs): - """Turn the switch off.""" - self._is_on = False -``` - -That's all there is to it to build a switch entity! Continue reading to learn more or check out the [video tutorial](https://youtu.be/Cfasc9EgbMU?t=737). - -## Updating the entity - -An entity represents a device. There are various strategies to keep your entity in sync with the state of the device, the most popular one being polling. - -### Polling - -With polling, Home Assistant will ask the entity from time to time (depending on the update interval of the component) to fetch the latest state. Home Assistant will poll an entity when the `should_poll` property returns `True` (the default value). You can either implement your update logic using `update()` or the async method `async_update()`. This method should fetch the latest state from the device and store it in an instance variable for the properties to return it. - -### Subscribing to updates - -When you subscribe to updates, your code is responsible for letting Home Assistant know that an update is available. Make sure you have the `should_poll` property return `False`. - -Whenever you receive new state from your subscription, you can tell Home Assistant that an update is available by calling `schedule_update_ha_state()` or async callback `async_schedule_update_ha_state()`. Pass in the boolean `True` to the method if you want Home Assistant to call your update method before writing the update to Home Assistant. - -## Generic properties - -The entity base class has a few properties that are common among all entities in Home Assistant. These can be added to any entity regardless of the type. All these properties are optional and don't need to be implemented. - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| assumed_state | boolean | `False` | Return `True` if the state is based on our assumption instead of reading it from the device. -| available | boolean | `True` | Indicate if Home Assistant is able to read the state and control the underlying device. -| device_state_attributes | dict | `None` | Extra information to store in the state machine. It needs to be information that further explains the state, it should not be static information like firmware version. See [below](entity_index.md#standard_attributes) for details of standard attributes. -| entity_picture | URL | `None` | Url of a picture to show for the entity. -| name | string | `None` | Name of the entity -| should_poll | boolean | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](#methods). -| unique_id | string | `None` | A unique identifier for this entity. Needs to be unique within a platform (ie `light.hue`). Should not be configurable by the user or be changeable. [Learn more.](entity_registry_index.md#unique-id-requirements) - -## Advanced properties - -The following properties are also available on entities. However, they are for advanced use only and should be used with caution. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| force_update | boolean | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine. -| hidden | boolean | `False` | Indicate if the entity should not be shown on the frontend. -| icon | icon | `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all devices. -| entity_registry_enabled_default | boolean | `True` | Indicate if the entity should be enabled or disabled when it is first added to the entity registry. - -## System properties - -The following properties are used and controlled by Home Assistant, and should not be overridden by integrations. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| enabled | boolean | `True` | Indicate if entity is enabled in the entity registry. It also returns `True` if the platform doesn't support the entity registry. Disabled entities will not be added to Home Assistant. - -## Standard attributes - -The following `device_state_attributes` are considered standard and should follow the convention below. The constant should be imported from `homeassistant/const.py`. - -| Name | Type | Unit | Constant | Description -| ---- | ---- | ---- | -------- | ----------- -| battery_charging | boolean | N/A | `ATTR_BATTERY_CHARGING` | Battery charging status of the entity, shown as a boolean `true` or `false`. If charging is not supported, then this attribute should not be created. -| battery_level | integer | % | `ATTR_BATTERY_LEVEL` | Battery level of the entity, shown as an integer percentage between 0-100. - -## Lifecycle hooks - -Use these lifecycle hooks to execute code when certain events happen to the entity. All lifecycle hooks are async methods. - -### `async_added_to_hass()` - -Called when an entity has their entity_id and hass object assigned, before it is written to the state machine for the first time. Example uses: restore the state, subscribe to updates or set callback/dispatch function/listener. - -### `async_will_remove_from_hass()` - -Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates. - -## Changing the entity model - -If you want to add a new feature to an entity or any of its subtypes (light, switch, etc), you will need to propose it first in our [architecture repo](https://github.com/home-assistant/architecture/issues). Only additions will be considered that are common features among various vendors. diff --git a/website/versioned_docs/version-0.98.0/entity_registry_disabled_by.md b/website/versioned_docs/version-0.98.0/entity_registry_disabled_by.md deleted file mode 100644 index a738ed7c..00000000 --- a/website/versioned_docs/version-0.98.0/entity_registry_disabled_by.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Entity Registry and disabling entities -sidebar_label: Disabling entities -id: version-0.98.0-entity_registry_disabled_by -original_id: entity_registry_disabled_by ---- - -The entity registry tracks all entities with unique IDs. For each entity, the registry keeps track of options that impact how the entity interacts with the core. One of these options is `disabled_by`. - -When `disabled_by` is set to a string value, the entity will not be added to Home Assistant when the integration passes it to `async_add_entities`. - -## Integration Architecture - -Integrations will need to make sure that they work correctly when their entities get disabled. If your integration is keeping references to the created entity objects, it should register those references only inside the entity's lifecycle method `async_added_to_hass`. This lifecycle method is only called if the entity is actually added to Home Assistant (and so it's not disabled). - -Entity disabling works with entities provided via a config entry or via an entry in configuration.yaml. If your integration is set up via a config entry and supports [unloading](config_entries_index.md#unloading-entries), Home Assistant will be able to reload your integration after entities have been enabled/disabled to apply the changes without a restart. - -## Users editing the entity registry - -One way an entity can be disabled is by the user editing the entity registry via the UI. In this case, the `disabled_by` value will be set to `user`. This will only work with entities that are already registered. - -## Integrations setting default value of disabled_by for new entity registry entries - -As an integration you can control if your entity is enabled when it is first registered. This is controlled by the `entity_registry_enabled_default` property. It defaults to `True`, which means the entity will be enabled. - -If the property returns `False`, the `disabled_by` value of the newly registered entity will be set to `integration`. - -## Config entry system options setting default value of disabled_by for new entity registry entries - -The user can also control how new entities that are related to a config entry are received by setting the system option `disable_new_entities` of a config entry to `True`. This can be done via the UI. - -If an entity is getting registered and this system option is set to `True`, the `disabled_by` property will be initialized as `config_entry`. - -If `disable_new_entities` is set to `True` and `entity_registry_enabled_default` returns `False`, the `disabled_by` value will be set to `integration`. - -## Integrations offering options to control disabled_by - -Some integrations will want to offer options to the user to control which entities are being added to Home Assistant. For example, the Unifi integration might want to offer to only include wireless clients but exclude wired clients. Another example is that the Hue integration offers an option to make the groups defined inside Hue available in Home Assistant. - -Integrations can offer options to users either via [configuration.yaml](configuration_yaml_index) or using an [Options Flow](config_entries_options_flow_handler.md). - -It is important that if an integration offers an option to change which entities are exposed that: - -- The option is only applied to existing integrations the first time it is set. It should not be applied on every reboot. This allows the user to enable individual entities. -- The option should impact the value of the entity property `entity_registry_enabled_default` so that new entities are disabled properly. diff --git a/website/versioned_docs/version-0.98.0/hassio_addon_config.md b/website/versioned_docs/version-0.98.0/hassio_addon_config.md deleted file mode 100644 index 73ee7309..00000000 --- a/website/versioned_docs/version-0.98.0/hassio_addon_config.md +++ /dev/null @@ -1,229 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.98.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - apparmor.txt - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -All our Images have also [bashio][bashio] installed. It contains a set of commonly used operations and can be used to be included in add-ons to reduce code duplication across add-ons and therefore making it easier to develop and maintain add-ons. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use bashio or `jq` inside your shell script to parse this data. - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -[bashio]: https://github.com/hassio-addons/bashio - -## Add-on Docker file - -All add-ons are based on latest Alpine Linux. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | yes | List of supported arch: `armhf`, `armv7`, `aarch64`, `amd64`, `i386`. -| machine | list | no | Default it support any machine type. You can select that this add-on run only on specific machines. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| udev | bool | no | Default False. Set this True, if your container run a own udev process. -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| homeassistant | string | no | Pin a minimum required Home Assistant version for such Add-on. Value is a version string like `0.91.2`. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| kernel_modules | bool | no | Map host kernel modules and config into add-on (readonly). -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| auth_api | bool | no | Allow access to Home Assistent user backend. -| ingress | bool | no | Enable the ingress feature for the Add-on -| ingress_port | integer | no | Default `8099`. For Add-ons they run on host network, you can use `0` and read the port later on API. -| ingress_entry | string | no | Modify the URL entry point from `/`. -| panel_icon | string | no | Default: mdi:puzzle. MDI icon for the menu panel integration. -| panel_title | string | no | Default add-on name, but can Modify with this options. -| panel_admin | bool | no | Default True. Make menu entry only available with admin privileged. - - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. - -We provide a set of [Base-Images][hassio-base] which should cover a lot of needs. If you don't want use the Alpine based version or need a specific Image tag, feel free to pin this requirements for you build with `build_from` option. - -[hassio-base]: https://github.com/home-assistant/hassio-base diff --git a/website/versioned_docs/version-0.98.0/hassio_addon_tutorial.md b/website/versioned_docs/version-0.98.0/hassio_addon_tutorial.md deleted file mode 100644 index c0a4588d..00000000 --- a/website/versioned_docs/version-0.98.0/hassio_addon_tutorial.md +++ /dev/null @@ -1,182 +0,0 @@ ---- -title: Tutorial: Making your first add-on -id: version-0.98.0-hassio_addon_tutorial -original_id: hassio_addon_tutorial ---- - -So you've got Home Assistant going and you've been enjoying the built-in add-ons but you're missing this one application. Time to make your own add-on! In Hass.io 0.24 we introduced the option to have local add-ons be build on your device. This is great for developing new add-ons locally. - -To get started with developing add-ons, we first need access to where Hass.io looks for local add-ons. For this you can use the Samba add-on or the SSH add-on. - -For Samba, once you have enabled and started it, your Hass.io instance will show up in your local network tab and share a folder called "addons". This is the folder to store your custom add-ons. - -If you are on macOS and the folder is not showing up automatically, go to Finder and press CMD+K then enter 'smb://hassio.local' - -![Screenshot of Windows Explorer showing a folder on the Hass.io server](/img/en/hass.io/tutorial/samba.png) - -For SSH, you will have to install it. Before you can start it, you will have to have a private/public key pair and store your public key in the add-on config ([see docs for more info][ssh]). Once started, you can SSH to Hass.io and store your custom add-ons in "/addons". - -![Screenshot of Putty connected to Hass.io](/img/en/hass.io/tutorial/ssh.png) - -Once you have located your add-on directory, it's time to get started! - -[ssh]: https://www.home-assistant.io/addons/ssh/ - -## Step 1: The basics - - - Create a new directory called `hello_world` - - Inside that directory create three files. - -`Dockerfile`: -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -`config.json`: -```json -{ - "name": "Hello world", - "version": "1", - "slug": "hello_world", - "description": "My first real add-on!", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {} -} -``` - -`run.sh`: -```bash -echo Hello world! -``` -Make sure your editor is using UNIX-like line breaks (LF), not Dos/Windows (CRLF). - -## Step 2: Installing and testing your add-on - -Now comes the fun part, time to open the Hass.io UI and install and run your add-on. - - - Open the Home Assistant frontend - - Go to the Hass.io panel - - On the top right click the shopping basket to go to the add-on store. - -![Screenshot of the Hass.io main panel](/img/en/hass.io/screenshots/main_panel_addon_store.png) - - - On the top right click the refresh button - - You should now see a new card called "Local" that lists your add-on! - -![Screenshot of the local repository card](/img/en/hass.io/screenshots/local_repository.png) - - - Click on your add-on to go to the add-on details page. - - Install your add-on - - Start your add-on - - Refresh the logs of your add-on, you should now see "Hello world!" in your logs. - -![Screenshot of the add-on logs](/img/en/hass.io/tutorial/addon_hello_world_logs.png) - -### I don't see my add-on?! - -Oops! You clicked refresh in the store and your add-on didn't show up. Or maybe you just updated an option, clicked refresh and saw your add-on disappear. - -When this happens, it means that your `config.json` is invalid. It's either invalid JSON or one of the specified options is incorrect. To see what went wrong, go to the Hass.io panel and in the supervisor card click on "View logs". This should bring you to a page with the logs of the supervisor. Scroll to the bottom and you should be able to find the validation error. - -Once you fixed the error, go to the add-on store and click refresh again. - -## Step 3: Hosting a server - -Until now we've been able to do some basic stuff, but it's not very useful yet. So let's take it one step further and host a server that we expose on a port. For this we're going to use the built-in HTTP server that comes with Python 3. - -To do this, we will need to update our files as follows: - - - `Dockerfile`: Install Python 3 - - `config.json`: Make the port from the container available on the host - - `run.sh`: Run the Python 3 command to start the HTTP server - -Add to your `Dockerfile` before `RUN`: - -``` -# Install requirements for add-on -RUN apk add --no-cache python3 - -# Python 3 HTTP Server serves the current working dir -# So let's set it to our add-on persistent data directory. -WORKDIR /data -``` - -Add "ports" to `config.json`. This will make TCP on port 8000 inside the container available on the host on port 8000. - -```json -{ - "name": "Hello world", - "version": "0.2", - "slug": "hello_world", - "description": "My first real add-on!", - "arch": ["armhf", "armv7", "aarch64", "amd64", "i386"], - "startup": "before", - "boot": "auto", - "options": {}, - "schema": {}, - "ports": { - "8000/tcp": 8000 - } -} -``` - -Update `run.sh` to start the Python 3 server: - -``` -python3 -m http.server 8000 -``` - -## Step 4: Installing the update - -Since we updated the version number in our `config.json`, Home Assistant will show an update button when looking at the add-on details. You might have to refresh your browser or click the refresh button in the add-on store for it to show up. If you did not update the version number, you can also uninstall and install the add-on again. After installing the add-on again, make sure you start it. - -Now navigate to [http://hassio.local:8000](http://hassio.local:8000) to see our server in action! - -![Screenshot of the file index served by the add-on](/img/en/hass.io/tutorial/python3-http-server.png) - -## Bonus: Working with add-on options - -In the screenshot you've probably seen that our server only served up 1 file: `options.json`. This file contains the user configuration for this add-on. Because we specified an empty "config" and "schema" in our `config.json`, the file is currently empty. - -Let's see if we can get some data into that file! - -To do this, we need to specify the default options and a schema for the user to change the options. - -Change the options and schema entries in your `config.json` with the following: - -```json -{ - … - - "options": { - "beer": true, - "wine": true, - "liquor": false, - "name": "world", - "year": 2017 - }, - "schema": { - "beer": "bool", - "wine": "bool", - "liquor": "bool", - "name": "str", - "year": "int" - }, - - … -} -``` - -Refresh the add-on store and re-install your add-on. You will now see the options available in the add-on config screen. When you now go back to our Python 3 server and download `options.json`, you'll see the options you set. [Example of how options.json can be used inside `run.sh`](https://github.com/home-assistant/hassio-addons/blob/master/mosquitto/data/run.sh#L4-L5) diff --git a/website/versioned_docs/version-0.99.0/creating_component_index.md b/website/versioned_docs/version-0.99.0/creating_component_index.md deleted file mode 100644 index 4a7440d2..00000000 --- a/website/versioned_docs/version-0.99.0/creating_component_index.md +++ /dev/null @@ -1,45 +0,0 @@ ---- -title: Creating your first integration -id: version-0.99.0-creating_component_index -original_id: creating_component_index ---- - -Alright, you learned about the [manifest](creating_integration_manifest.md), so it's time to write your first code for your integration. AWESOME. Don't worry, we've tried hard to keep it as easy as possible. From a Home Assistant development environment, type the following and follow the instructions: - -```python -python3 -m script.scaffold -``` - -This will set you up with everything that you need to build an integration that is able to be set up via the user interface. More extensive examples of integrations are available from [our example repository](https://github.com/home-assistant/example-custom-config/tree/master/custom_components/). - -## The minimum - -The scaffold integration contains a bit more than just the bare minimum. The minimum is that you define a `DOMAIN` constant that contains the domain of the integration. The second part is that it needs to define a setup method that returns a boolean if the set up was successful. - -```python -DOMAIN = 'hello_state' - -def setup(hass, config): - hass.states.set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -And if you prefer an async component: - -```python -DOMAIN = 'hello_state' - -async def async_setup(hass, config): - hass.states.async_set('hello_state.world', 'Paulus') - - # Return boolean to indicate that initialization was successful. - return True -``` - -To load this, add `hello_state:` to your `configuration.yaml` file and create a file `/custom_components/hello_state/__init__.py` with one of the two codeblocks above to test it locally. - -## What the scaffold offers - -When using the scaffold script, it will go past the bare minimum of an integration. It will include a config flow, tests for the config flow and basic translation infrastructure to provide internationalization for your config flow. diff --git a/website/versioned_docs/version-0.99.0/dev_101_states.md b/website/versioned_docs/version-0.99.0/dev_101_states.md deleted file mode 100644 index 0263901c..00000000 --- a/website/versioned_docs/version-0.99.0/dev_101_states.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Using States -id: version-0.99.0-dev_101_states -original_id: dev_101_states ---- - -Home Assistant keeps track of the states of entities in a state machine. The state machine has very few requirements: - - - Each state is related to an entity identified by an entity id. This id is made up of a domain and an object id. For example `light.kitchen_ceiling`. You can make up any combination of domain and object id, even overwriting existing states. - - Each state has a primary attribute that describes the state of the entity. In the case of a light this could be for example "on" and "off". You can store anything you want in the state, as long as it's a string (will be converted if it's not). - - You can store more information about an entity by setting attributes. Attributes is a dictionary that can contain any data that you want. The only requirement is that it's JSON serializable, so you're limited to numbers, strings, dictionaries and lists. - -[Description of the state object.](https://www.home-assistant.io/docs/configuration/state_object/) - -## Using states in your component - -This is a simple tutorial/example on how to create and set states. We will do our work in a component called "hello_state". The purpose of this component is to display a given text in the frontend. - -To get started, create the file `/custom_components/hello_state.py` and copy the below example code. - -```python -""" -Support for showing text in the frontend. - -For more details about this component, please refer to the documentation at -https://developers.home-assistant.io/docs/en/dev_101_states.html -""" -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = 'hello_state' - -def setup(hass, config): - """Setup the Hello State component. """ - _LOGGER.info("The 'hello state' component is ready!") - - return True -``` - -1. In the file header we decided to add some details: A short description and the link to the documentation. -2. We want to do some logging. This means that we import the Python logging module and create an alias. -3. The component name is equal to the domain name. -4. The `setup` function will take care of the initialization of our component. - The component will only write a log message. Keep in mind for later that you have several options for the severity: - - - `_LOGGER.info(msg)` - - `_LOGGER.warning(msg)` - - `_LOGGER.error(msg)` - - `_LOGGER.critical(msg)` - - `_LOGGER.exception(msg)` - -5. We return `True` if everything is ok. - -Add the component to your `configuration.yaml` file. - -```yaml -hello_state: -``` - -After a start or a restart of Home Assistant the component will create an entry in the log. - -```bash -16-03-12 14:16:42 INFO (MainThread) [custom_components.hello_state] The 'hello state' component is ready! -``` - -The next step is the introduction of configuration options. A user can pass configuration options to our component via `configuration.yaml`. To use them we'll use the passed in `config` variable to our `setup` method. - -```python -import logging - -_LOGGER = logging.getLogger(__name__) - -DOMAIN = 'hello_state' - -CONF_TEXT = 'text' -DEFAULT_TEXT = 'No text!' - -def setup(hass, config): - """Set up the Hello State component. """ - # Get the text from the configuration. Use DEFAULT_TEXT if no name is provided. - text = config[DOMAIN].get(CONF_TEXT, DEFAULT_TEXT) - - # States are in the format DOMAIN.OBJECT_ID - hass.states.set('hello_state.Hello_State', text) - - return True -``` - -To use the latest feature of our component, update the entry in your `configuration.yaml` file. - -```yaml -hello_state: - text: 'Hello, World!' -``` - -Thanks to `DEFAULT_TEXT` variable the component will launch even if no `text:` field is used in the `configuration.yaml` file. Quite often there are variables which are required. It's important to check if all mandatory configuration variables are provided. If not, the setup should fail. We will use `voluptuous` as a helper to achieve this. The next listing shows the essential parts. - -```python -import voluptuous as vol - -import homeassistant.helpers.config_validation as cv - -CONFIG_SCHEMA = vol.Schema({ - DOMAIN: vol.Schema({ - vol.Required(CONF_TEXT): cv.string, - }) -}, extra=vol.ALLOW_EXTRA) -``` - -Now, when `text:` is missing from the config, Home Assistant will alert the user and not setup your component. - -After a start or a restart of Home Assistant the component will be visible in the frontend if the `configuration.yaml` file is up-to-date. - -

- -

- -In order to expose attributes for a platform, you will need to define a property called `device_state_attributes` on the entity class, which will return a dictionary of attributes: - -``` -@property -def device_state_attributes(self): - """Return device specific state attributes.""" - return self._attributes -``` - -> Entities also have a similar property `state_attributes`, which normally doesn't need to be defined by new platforms. This property is used by base components to add standard sets of attributes to a state. Example: The light component uses `state_attributes` to add brightness to the state dictionary. If you are designing a new component, you should define `state_attributes` instead. - -To get your component included in the Home Assistant releases, follow the steps described in the [Submit your work](development_submitting.md) section. Basically you only need to move your component in the `homeassistant/component/` directory of your fork and create a Pull Request. diff --git a/website/versioned_docs/version-0.99.0/development_checklist.md b/website/versioned_docs/version-0.99.0/development_checklist.md deleted file mode 100644 index 671742a5..00000000 --- a/website/versioned_docs/version-0.99.0/development_checklist.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Development Checklist -sidebar_label: Introduction -id: version-0.99.0-development_checklist -original_id: development_checklist ---- - - -Before you commit any changes, check your work against these requirements: - -- All communication to external devices or services must be wrapped in an external Python library hosted on [pypi](https://pypi.python.org/pypi). -- New dependencies are added to `requirements_all.txt` (if applicable), using `python3 -m script.gen_requirements_all` -- New codeowners are added to `CODEOWNERS` (if applicable), using `python3 -m script.hassfest` -- The `.coveragerc` file is updated to exclude your platform if there are no tests available or your new code uses a third-party library for communication with the device, service, or sensor -- The code is formatted using Black, as per these [guidelines](https://developers.home-assistant.io/blog/2019/07/31/black.html). This can be done running the command `black --fast homeassistant`. -- Documentation is developed for [home-assistant.io](https://home-assistant.io/) - * Visit the [website documentation](https://www.home-assistant.io/developers/documentation/) for more information about contributing to [home-assistant.io](https://github.com/home-assistant/home-assistant.github.io). diff --git a/website/versioned_docs/version-0.99.0/entity_weather.md b/website/versioned_docs/version-0.99.0/entity_weather.md deleted file mode 100644 index 7a9b370f..00000000 --- a/website/versioned_docs/version-0.99.0/entity_weather.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Weather Entity -sidebar_label: Weather -id: version-0.99.0-entity_weather -original_id: entity_weather ---- - -## Properties - -> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| state | string | **Required** | The current weather condition. -| temperature | float | **Required** | The current temperature in °C or °F. -| pressure | float | `None` | The current air pressure in hPa or inHg. -| humidity | float | `None` | The current humidity in %. -| visibility | float | `None` | The current visibility in km or mi. -| wind_speed | float | `None` | The current wind speed in km/h or mi/h. -| wind_bearing | string | `None` | The current wind bearing, 1-3 letters. -| forecast | array | `None` | Daily or Hourly forecast data. -| attribution | string | `None` | The branding text required by the API provider. - -Properties have to follow the units defined in the `unit_system`. - -### Forecast - -Forecast data should either be daily or hourly. - -| Name | Type | Default | Description -| ---- | ---- | ------- | ----------- -| datetime | string | **Required** | UTC Date time in RFC 3339 format. -| temperature | float | **Required** | The higher temperature in °C or °F -| condition | string | `None` | The weather condition at this point. -| templow | float | `None` | The lower daily Temperature in °C or °F - -### Recommended values for state and condition - -These weather conditions are included in our translation files and also show the corresponding icon. - -| Condition | Description -| --------- | ----------- -| clear-night | Clear night -| cloudy | Many clouds -| exceptional | Exceptional -| fog | Fog -| hail | Hail -| lightning | Lightning/ thunderstorms -| lightning-rainy | Lightning/ thunderstorms and rain -| partlycloudy | A few clouds -| pouring | Pouring rain -| rainy | Rain -| snowy | Snow -| snowy-rainy | Snow and Rain -| sunny | Sunshine -| windy | Wind -| windy-variant | Wind and clouds - -This means that the `weather` platforms don't need to support languages. diff --git a/website/versioned_docs/version-0.99.0/hassio_addon_config.md b/website/versioned_docs/version-0.99.0/hassio_addon_config.md deleted file mode 100644 index 4a43e517..00000000 --- a/website/versioned_docs/version-0.99.0/hassio_addon_config.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: Add-On Configuration -id: version-0.99.0-hassio_addon_config -original_id: hassio_addon_config ---- - -Each add-on is stored in a folder. The file structure looks like this: - -```text -addon_name/ - apparmor.txt - build.json - CHANGELOG.md - config.json - Dockerfile - icon.png - logo.png - README.md - run.sh -``` - -## Add-on script - -As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things. - -All our Images have also [bashio][bashio] installed. It contains a set of commonly used operations and can be used to be included in add-ons to reduce code duplication across add-ons and therefore making it easier to develop and maintain add-ons. - -When developing your script: - - - `/data` is a volume for persistent storage. - - `/data/options.json` contains the user configuration. You can use bashio or `jq` inside your shell script to parse this data. - -```bash -CONFIG_PATH=/data/options.json - -TARGET="$(jq --raw-output '.target' $CONFIG_PATH)" -``` - -So if your `options` contain -```json -{ "target": "beer" } -``` -then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards. - -[bashio]: https://github.com/hassio-addons/bashio - -## Add-on Docker file - -All add-ons are based on latest Alpine Linux. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images. - -``` -ARG BUILD_FROM -FROM $BUILD_FROM - -ENV LANG C.UTF-8 - -# Install requirements for add-on -RUN apk add --no-cache jq - -# Copy data for add-on -COPY run.sh / -RUN chmod a+x /run.sh - -CMD [ "/run.sh" ] -``` - -If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include: -``` -LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64" -``` - -It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`. - -### Build Args - -We support the following build arguments by default: - -| ARG | Description | -|-----|-------------| -| BUILD_FROM | Hold image for dynamic builds or buildings over our systems. -| BUILD_VERSION | Add-on version (read from `config.json`). -| BUILD_ARCH | Hold current build arch inside. - -## Add-on config - -The config for an add-on is stored in `config.json`. - -```json -{ - "name": "xy", - "version": "1.2", - "slug": "folder", - "description": "long description", - "arch": ["amd64"], - "url": "website with more information about add-on (ie a forum thread for support)", - "startup": "application", - "boot": "auto", - "ports": { - "123/tcp": 123 - }, - "map": ["config:rw", "ssl"], - "options": {}, - "schema": {}, - "image": "repo/{arch}-my-custom-addon" -} -``` - -| Key | Type | Required | Description | -| --- | ---- | -------- | ----------- | -| name | string | yes | Name of the add-on -| version | string | yes | Version of the add-on -| slug | string | yes | Slug of the add-on -| description | string | yes | Description of the add-on -| arch | list | yes | List of supported arch: `armhf`, `armv7`, `aarch64`, `amd64`, `i386`. -| machine | list | no | Default it support any machine type. You can select that this add-on run only on specific machines. -| url | url | no | Homepage of the addon. Here you can explain the add-ons and options. -| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon. -| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`. -| boot | string | yes | `auto` by system and manual or only `manual` -| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`. If host-port is `null`, the mapping is disabled. -| ports_description | dict | no | Network ports description mapping. Format is `"container-port/type": "description of this port"`. -| host_network | bool | no | If that is True, the add-on run on host network. -| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others. -| host_dbus | bool | no | Default False. Map Host dbus service into add-on. -| host_pid | bool | no | Default False. Allow to run container on host PID namespace. Work only for not protected add-ons. -| devices | list | no | Device list to map into the add-on. Format is: `::`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm` -| udev | bool | no | Default False. Set this True, if your container run a own udev process. -| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on. -| homeassistant | string | no | Pin a minimum required Home Assistant version for such Add-on. Value is a version string like `0.91.2`. -| hassio_role | str | no | Default `default`. Role based access to Hass.io API. Available: `default`, `homeassistant`, `backup`, `manager`, `admin`. -| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`. -| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`. -| docker_api | bool | no | Allow read-oly access to docker API for add-on. Work only for not protected add-ons. -| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`, `SYS_RESOURCE`, `SYS_PTRACE`, `SYS_MODULE`, `DAC_READ_SEARCH`. -| full_access | bool | no | Give full access to hardware like the privileged mode in docker. Work only for not protected add-ons. -| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile. -| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name. -| environment | dict | no | A dict of environment variable to run add-on. -| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic. -| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device. On system with AppArmor enabled, you need disable AppArmor or better for security, provide you own profile for the add-on. -| devicetree | bool | no | Boolean. If this is set to True, `/device-tree` will map into add-on. -| kernel_modules | bool | no | Map host kernel modules and config into add-on (readonly). -| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API. -| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data. -| options | dict | yes | Default options value of the add-on -| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options. -| image | string | no | For use with Docker Hub and other container registries. -| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed. -| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional. -| discovery | list | no | A list of services they this Add-on allow to provide for Home Assistant. Currently supported: `mqtt` -| services | list | no | A list of services they will be provided or consumed with this Add-on. Format is `service`:`function` and functions are: `provide` (this add-on can provide this service), `want` (this add-on can use this service) or `need` (this add-on need this service to work correctly). -| auth_api | bool | no | Allow access to Home Assistent user backend. -| ingress | bool | no | Enable the ingress feature for the Add-on -| ingress_port | integer | no | Default `8099`. For Add-ons they run on host network, you can use `0` and read the port later on API. -| ingress_entry | string | no | Modify the URL entry point from `/`. -| panel_icon | string | no | Default: mdi:puzzle. MDI icon for the menu panel integration. -| panel_title | string | no | Default add-on name, but can Modify with this options. -| panel_admin | bool | no | Default True. Make menu entry only available with admin privileged. - - -### Options / Schema - -The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value. - -```json -{ - "message": "custom things", - "logins": [ - { "username": "beer", "password": "123456" }, - { "username": "cheep", "password": "654321" } - ], - "random": ["haha", "hihi", "huhu", "hghg"], - "link": "http://example.com/", - "size": 15, - "count": 1.2 -} -``` - -The `schema` looks like `options` but describes how we should validate the user input. For example: - -```json -{ - "message": "str", - "logins": [ - { "username": "str", "password": "str" } - ], - "random": ["match(^\w*$)"], - "link": "url", - "size": "int(5,20)", - "count": "float", - "not_need": "str?" -} -``` - -We support: -- str / str(min,) / str(,max) / str(min,max) -- bool -- int / int(min,) / int(,max) / int(min,max) -- float / float(min,) / float(,max) / float(min,max) -- email -- url -- port -- match(REGEX) -- list(val1|val2|...) - -## Add-on extended build - -Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems. -You need this only, if you not use the default images or need additionals things. - -```json -{ - "build_from": { - "armhf": "mycustom/base-image:latest" - }, - "squash": false, - "args": { - "my_build_arg": "xy" - } -} -``` - -| Key | Required | Description | -| --- | -------- | ----------- | -| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value. -| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that! -| args | no | Allow to set additional Docker build arguments as a dictionary. - -We provide a set of [Base-Images][hassio-base] which should cover a lot of needs. If you don't want use the Alpine based version or need a specific Image tag, feel free to pin this requirements for you build with `build_from` option. - -[hassio-base]: https://github.com/home-assistant/hassio-base diff --git a/website/versioned_docs/version-0.99.0/lovelace_custom_card.md b/website/versioned_docs/version-0.99.0/lovelace_custom_card.md deleted file mode 100644 index 6dde217e..00000000 --- a/website/versioned_docs/version-0.99.0/lovelace_custom_card.md +++ /dev/null @@ -1,243 +0,0 @@ ---- -title: Lovelace: Custom Cards -id: version-0.99.0-lovelace_custom_card -original_id: lovelace_custom_card ---- - -[Lovelace](https://www.home-assistant.io/lovelace/) is our new approach to defining your user interface for Home Assistant. We offer a lot of built-in cards, but you're not just limited to the ones that we decided to include in the Lovelace UI. You can build and use your own! - -## API - -You define your custom card as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). It's up to you to decide how to render your DOM inside your element. You can use Polymer, Angular, Preact or any other popular framework (except for React – [more info on React here](https://custom-elements-everywhere.com/#react)). - -```js -const element = document.createElement('some-custom-card'); -``` - -Home Assistant will call `setConfig(config)` when the configuration changes (rare). If you throw an exception if the configuration is invalid, Lovelace will render an error card to notify the user. - -```js -try { - element.setConfig(config); -} catch (err) { - showErrorCard(err.message, config); -} -``` - -Home Assistant will set the `hass` property when the state of Home Assistant changes (frequent). Whenever the state changes, the component will have to update itself to represent the latest state. - -```js -element.hass = hass; -``` - -Your card can define a `getCardSize` method that returns the size of your card as a number. A height of 1 is equivalent to 50 pixels. This will help Home Assistant distribute the cards evenly over the columns. A card size of `1` will be assumed if the method is not defined. - -```js -if ('getCardSize' in element) { - return element.getCardSize(); -} else { - return 1; -} -``` - -## Defining your card - -Create a new file in your Home Assistant config dir as `/www/content-card-example.js` and put in the following contents: - -```js -class ContentCardExample extends HTMLElement { - set hass(hass) { - if (!this.content) { - const card = document.createElement('ha-card'); - card.header = 'Example card'; - this.content = document.createElement('div'); - this.content.style.padding = '0 16px 16px'; - card.appendChild(this.content); - this.appendChild(card); - } - - const entityId = this.config.entity; - const state = hass.states[entityId]; - const stateStr = state ? state.state : 'unavailable'; - - this.content.innerHTML = ` - The state of ${entityId} is ${stateStr}! -

- - `; - } - - setConfig(config) { - if (!config.entity) { - throw new Error('You need to define an entity'); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return 3; - } -} - -customElements.define('content-card-example', ContentCardExample); -``` - -## Referencing your new card - -In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `/www` directory, it will be accessible in your browser via the url `/local/` (if you have recently added the www folder you will need to re-start home assistant for files to be picked up). - -```yaml -# Example Lovelace configuration -resources: - - url: /local/content-card-example.js - type: js -views: -- name: Example - cards: - - type: "custom:content-card-example" - entity: input_boolean.switch_tv -``` - -## Advanced example - -Resources to load in Lovelace can be imported as a JS script, an HTML import or as a JS module import. Below is an example of a custom card using JS modules that does all the fancy things. - -![Screenshot of the wired card](/img/en/frontend/lovelace-ui-custom-card-screenshot.png) - -Create a new file in your Home Assistant config dir as `/www/wired-cards.js` and put in the following contents: - -```js -import "https://unpkg.com/wired-card@0.8.1/wired-card.js?module"; -import "https://unpkg.com/wired-toggle@0.8.0/wired-toggle.js?module"; -import { - LitElement, - html, - css -} from "https://unpkg.com/lit-element@2.0.1/lit-element.js?module"; - -function loadCSS(url) { - const link = document.createElement("link"); - link.type = "text/css"; - link.rel = "stylesheet"; - link.href = url; - document.head.appendChild(link); -} - -loadCSS("https://fonts.googleapis.com/css?family=Gloria+Hallelujah"); - -class WiredToggleCard extends LitElement { - static get properties() { - return { - hass: {}, - config: {} - }; - } - - render() { - return html` - - ${this.config.entities.map(ent => { - const stateObj = this.hass.states[ent]; - return stateObj - ? html` -
- ${stateObj.attributes.friendly_name} - -
- ` - : html` -
Entity ${ent} not found.
- `; - })} -
- `; - } - - setConfig(config) { - if (!config.entities) { - throw new Error("You need to define entities"); - } - this.config = config; - } - - // The height of your card. Home Assistant uses this to automatically - // distribute all cards over the available columns. - getCardSize() { - return this.config.entities.length + 1; - } - - _toggle(state) { - this.hass.callService("homeassistant", "toggle", { - entity_id: state.entity_id - }); - } - - static get styles() { - return css` - :host { - font-family: "Gloria Hallelujah", cursive; - } - wired-card { - background-color: white; - padding: 16px; - display: block; - font-size: 18px; - } - .state { - display: flex; - justify-content: space-between; - padding: 8px; - align-items: center; - } - .not-found { - background-color: yellow; - font-family: sans-serif; - font-size: 14px; - padding: 8px; - } - wired-toggle { - margin-left: 8px; - } - `; - } -} -customElements.define("wired-toggle-card", WiredToggleCard); -``` - -And for your configuration: - -```yaml -# Example Lovelace configuration -resources: - - url: /local/wired-cards.js - type: module -views: -- name: Example - cards: - - type: "custom:wired-toggle-card" - entities: - - input_boolean.switch_ac_kitchen - - input_boolean.switch_ac_livingroom - - input_boolean.switch_tv -``` - -## Recommended Design Elements -We are currently migrating from using Paper Elements to MWC (Material Web Component) Elements. - -If an element exists in the below repository for MWC. We recommended using it. -- [MWC (Material Web Components)](https://material-components.github.io/material-components-web-components/demos/index.html) - -If an element does not exist in MWC, we default to using Paper Elements. -- [Paper Elements](https://www.webcomponents.org/collection/PolymerElements/paper-elements) - -## Advanced Resources -Community Maintained Boiler Plate Card - Advanced Template (Typescript, Rollup, Linting, etc.) -- [Boilerplate Card](https://github.com/custom-cards/boilerplate-card) - -Developer Documentation for [HACS](https://hacs.netlify.com/) (Home Assitant Community Store). -- [HACS Plugin Docs](https://hacs.netlify.com/developer/plugin/) diff --git a/website/versioned_docs/version-0.99.3/device_automation_action.md b/website/versioned_docs/version-0.99.3/device_automation_action.md deleted file mode 100644 index 51810d57..00000000 --- a/website/versioned_docs/version-0.99.3/device_automation_action.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Device Actions -sidebar_label: Actions -id: version-0.99.3-device_automation_action -original_id: device_automation_action ---- - -Device actions allow a user to have a device do something. Examples are to turn a light on or open a door. - -Device actions are defined as dictionaries. These dictionaries are created by your integration and are passed to your integration to create a function that performs the action. - -Device actions can be provided by the integration that provides the device (e.g. ZHA, deCONZ) or the entity integrations that the device has entities with (e.g. light, switch). -An example of the former could be to reboot the device, while an example of the latter could be to turn a light on. - -Home Assistant includes a template to get started with device actions. To get started, run inside a development environment `python3 -m script.scaffold device_action`. - -The template will create a new file `device_action.py` in your integration folder and a matching test file. The file contains the following functions and constants: - -## `ACTION_SCHEMA` - -This is the schema for actions. The base schema should be extended from `homeassistant.helpers.config_validation.DEVICE_ACTION_BASE_SCHEMA`. - -## `async async async_get_actions(hass, device_id)` - -Return a list of actions that this device supports. - -## `async async_call_action_from_config(hass, config, variables, context)` - -Execute the passed in action. diff --git a/website/versioned_docs/version-0.99.3/device_automation_condition.md b/website/versioned_docs/version-0.99.3/device_automation_condition.md deleted file mode 100644 index f8b47d12..00000000 --- a/website/versioned_docs/version-0.99.3/device_automation_condition.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Device Conditions -sidebar_label: Conditions -id: version-0.99.3-device_automation_condition -original_id: device_automation_condition ---- - -Device conditions allow a user to check if a certain condition is met. Examples are is a light on or is the floor wet. - -Device conditions are defined as dictionaries. These dictionaries are created by your integration and are passed to your integration to create a a function that checks the condition. - -Device conditions can be provided by the integration that provides the device (e.g. ZHA, deCONZ) or the entity integrations that the device has entities with (e.g. light, humidity sensor). -An example of the latter could be to check if a light is on or the floor is wet. - -Home Assistant includes a template to get started with device conditions. To get started, run inside a development environment `python3 -m script.scaffold device_condition`. - -The template will create a new file `device_condition.py` in your integration folder and a matching test file. The file contains the following functions and constants: - -## `CONDITION_SCHEMA` - -This is the schema for conditions. The base schema should be extended from `homeassistant.helpers.config_validation.DEVICE_CONDITION_BASE_SCHEMA`. - -## `async async_get_conditions(hass, device_id)` - -Return a list of conditions that this device supports. - -## `async async_condition_from_config(config, config_validation)` - -Create a condition function from a function. The condition functions should be an async-friendly callback that evaluates the condition and returns a `bool`. diff --git a/website/versioned_docs/version-0.99.3/device_automation_index.md b/website/versioned_docs/version-0.99.3/device_automation_index.md deleted file mode 100644 index eab7b01b..00000000 --- a/website/versioned_docs/version-0.99.3/device_automation_index.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Device Automations -sidebar_label: Introduction -id: version-0.99.3-device_automation_index -original_id: device_automation_index ---- - -Device Automations provide users with a device-centric layer on top of the core concepts of Home Assistant. When creating automations, users no longer have to deal with core concepts like states and events. Instead, they will be able to pick a device and then pick from a list of pre-defined triggers, conditions and actions. - -Integrations can hook into this system by exposing functions to generate the pre-defined triggers, conditions, actions and having functions that can listen for the triggers, check the condition and execute the action. - -Device automations are not exposing extra functionality but are a way for users to not have to learn new concepts. Device automations are using events, state and service helpers under the hood. diff --git a/website/versioned_docs/version-0.99.3/device_automation_trigger.md b/website/versioned_docs/version-0.99.3/device_automation_trigger.md deleted file mode 100644 index ef4c6536..00000000 --- a/website/versioned_docs/version-0.99.3/device_automation_trigger.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: Device Triggers -sidebar_label: Triggers -id: version-0.99.3-device_automation_trigger -original_id: device_automation_trigger ---- - -Device triggers are automation triggers that are tied to a specific device. Examples are "light turned on" or "water detected". - -Device triggers are defined as dictionaries. These dictionaries are created by your integration and are consumed by your integration to attach the trigger. - -Device triggers can be provided by the integration that provides the device (e.g. ZHA, deCONZ) or the entity integrations that the device has entities with (e.g. light, switch). -An example of the former is events not tied to an entity e.g. key press on a remote control or touch panel, while an example of the latter could be that a light has been turned on. - -Home Assistant includes a template to get started with device triggers. To get started, run inside a development environment `python3 -m script.scaffold device_trigger`. - -The template will create a new file `device_trigger.py` in your integration folder and a matching test file. The file contains the following functions and constants: - -## `TRIGGER_SCHEMA` - -This is a voluptuous schema that verifies that a specific dictionary represents a config that your integration can handle. This should extend the TRIGGER_BASE_SCHEMA from `device_automation/__init__.py`. - -## `async async_get_triggers(hass, device_id)` - -Return a list of triggers. - -## `async async_attach_trigger(hass, config, action, automation_info)` - -Given one of your own trigger configs, make it so the `action` is called whenever the trigger is triggered. Return value is a function that detaches the trigger. diff --git a/website/versioned_docs/version-0.99.3/reproduce_state_index.md b/website/versioned_docs/version-0.99.3/reproduce_state_index.md deleted file mode 100644 index 0f735e57..00000000 --- a/website/versioned_docs/version-0.99.3/reproduce_state_index.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: Reproduce State / Scene support -id: version-0.99.3-reproduce_state_index -original_id: reproduce_state_index ---- - -Home Assistant has support for scenes. Scenes are a collection of (partial) entity states. When a scene is activated, Home Assistant will try to call the right services to get the specified scenes in their specified state. - -Integrations are responsible for adding support to Home Assistant to be able to call the right services to reproduce the states in a scene. - -## Adding support - -The quickest way to add reproduce state support to a new integration is by using our built-in scaffold template. From a Home Assistant dev environment, run `python3 -m script.scaffold reproduce_state` and follow the instructions. - -If you prefer to go the manual route, create a new file in your integration folder called `reproduce_state.py` and implement the following method: - -```python -import asyncio -from typing import Iterable, Optional -from homeassistant.core import Context, State -from homeassistant.helpers.typing import HomeAssistantType - -async def async_reproduce_states( - hass: HomeAssistantType, states: Iterable[State], context: Optional[Context] = None -) -> None: - """Reproduce component states.""" - # TODO reproduce states -``` diff --git a/website/versioned_sidebars/version-0.101.0-sidebars.json b/website/versioned_sidebars/version-0.101.0-sidebars.json deleted file mode 100644 index 9d4bd791..00000000 --- a/website/versioned_sidebars/version-0.101.0-sidebars.json +++ /dev/null @@ -1,182 +0,0 @@ -{ - "version-0.101.0-Architecture": { - "Architecture": [ - "version-0.101.0-architecture_index", - "version-0.101.0-architecture_components", - "version-0.101.0-architecture_entities", - "version-0.101.0-architecture_hassio" - ], - "Entities": [ - "version-0.101.0-entity_index", - "version-0.101.0-entity_air_quality", - "version-0.101.0-entity_alarm_control_panel", - "version-0.101.0-entity_binary_sensor", - "version-0.101.0-entity_climate", - "version-0.101.0-entity_cover", - "version-0.101.0-entity_fan", - "version-0.101.0-entity_light", - "version-0.101.0-entity_lock", - "version-0.101.0-entity_media_player", - "version-0.101.0-entity_remote", - "version-0.101.0-entity_sensor", - "version-0.101.0-entity_switch", - "version-0.101.0-entity_vacuum", - "version-0.101.0-entity_water_heater", - "version-0.101.0-entity_weather" - ], - "Authentication": [ - "version-0.101.0-auth_index", - "version-0.101.0-auth_permissions", - "version-0.101.0-auth_api", - "version-0.101.0-auth_auth_provider", - "version-0.101.0-auth_auth_module" - ], - "Config Entries": [ - "version-0.101.0-config_entries_index" - ], - "Data Entry Flow": [ - "version-0.101.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.101.0-entity_registry_index", - "version-0.101.0-entity_registry_disabled_by" - ], - "Device Registry": [ - "version-0.101.0-device_registry_index" - ], - "Area Registry": [ - "version-0.101.0-area_registry_index" - ] - }, - "version-0.101.0-Extending Frontend": { - "Frontend": [ - "version-0.101.0-frontend_index", - "version-0.101.0-frontend_architecture", - "version-0.101.0-frontend_development", - "version-0.101.0-frontend_data", - "version-0.101.0-frontend_external_auth", - "version-0.101.0-frontend_external_bus" - ], - "Extending the frontend": [ - "version-0.101.0-frontend_add_card", - "version-0.101.0-frontend_add_more_info", - "version-0.101.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.101.0-lovelace_custom_card", - "version-0.101.0-frontend_creating_custom_panels" - ] - }, - "version-0.101.0-Extending HASS": { - "Development Workflow": [ - "version-0.101.0-development_index", - "version-0.101.0-development_environment", - "version-0.101.0-development_submitting", - "version-0.101.0-development_guidelines", - "version-0.101.0-development_testing", - "version-0.101.0-development_catching_up" - ], - "Building Integrations": [ - "version-0.101.0-creating_integration_file_structure", - "version-0.101.0-creating_integration_manifest", - "version-0.101.0-creating_component_index", - "version-0.101.0-config_entries_config_flow_handler", - "version-0.101.0-config_entries_options_flow_handler", - "version-0.101.0-configuration_yaml_index", - "version-0.101.0-dev_101_services", - "version-0.101.0-creating_platform_index", - "version-0.101.0-creating_component_generic_discovery", - "version-0.101.0-reproduce_state_index" - ], - "Development Checklist": [ - "version-0.101.0-development_checklist", - "version-0.101.0-creating_component_code_review", - "version-0.101.0-creating_platform_code_review", - "version-0.101.0-integration_quality_scale_index" - ], - "Home Assistant Core 101": [ - "version-0.101.0-dev_101_index", - "version-0.101.0-dev_101_hass", - "version-0.101.0-dev_101_events", - "version-0.101.0-dev_101_states", - "version-0.101.0-dev_101_config" - ], - "Device Automations": [ - "version-0.101.0-device_automation_index", - "version-0.101.0-device_automation_trigger", - "version-0.101.0-device_automation_condition", - "version-0.101.0-device_automation_action" - ], - "Misc": [ - "version-0.101.0-development_validation", - "version-0.101.0-development_typing" - ] - }, - "version-0.101.0-Misc": { - "Introduction": [ - "version-0.101.0-misc" - ], - "External API": [ - "version-0.101.0-external_api_rest", - "version-0.101.0-external_api_rest_python", - "version-0.101.0-external_api_websocket", - "version-0.101.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.101.0-internationalization_index", - "version-0.101.0-internationalization_backend_localization", - "version-0.101.0-internationalization_custom_component_localization", - "version-0.101.0-internationalization_translation" - ], - "Documentation": [ - "version-0.101.0-documentation_index", - "version-0.101.0-documentation_standards", - "version-0.101.0-documentation_create_page" - ], - "Intents": [ - "version-0.101.0-intent_index", - "version-0.101.0-intent_firing", - "version-0.101.0-intent_handling", - "version-0.101.0-intent_conversation", - "version-0.101.0-intent_builtin" - ], - "Native App Integration": [ - "version-0.101.0-app_integration_index", - "version-0.101.0-app_integration_setup", - "version-0.101.0-app_integration_sending_data", - "version-0.101.0-app_integration_sensors", - "version-0.101.0-app_integration_notifications", - "version-0.101.0-app_integration_webview" - ], - "Building a Python library": [ - "version-0.101.0-api_lib_index", - "version-0.101.0-api_lib_auth", - "version-0.101.0-api_lib_data_models" - ], - "asyncio": [ - "version-0.101.0-asyncio_index", - "version-0.101.0-asyncio_101", - "version-0.101.0-asyncio_categorizing_functions", - "version-0.101.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.101.0-hassio_debugging", - "version-0.101.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.101.0-hassio_addon_index", - "version-0.101.0-hassio_addon_tutorial", - "version-0.101.0-hassio_addon_config", - "version-0.101.0-hassio_addon_communication", - "version-0.101.0-hassio_addon_testing", - "version-0.101.0-hassio_addon_publishing", - "version-0.101.0-hassio_addon_presentation", - "version-0.101.0-hassio_addon_repository", - "version-0.101.0-hassio_addon_security" - ], - "Maintainer docs": [ - "version-0.101.0-maintenance", - "version-0.101.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.105.0-sidebars.json b/website/versioned_sidebars/version-0.105.0-sidebars.json deleted file mode 100644 index 10771c36..00000000 --- a/website/versioned_sidebars/version-0.105.0-sidebars.json +++ /dev/null @@ -1,183 +0,0 @@ -{ - "version-0.105.0-Architecture": { - "Architecture": [ - "version-0.105.0-architecture_index", - "version-0.105.0-architecture_components", - "version-0.105.0-architecture_entities", - "version-0.105.0-architecture_hassio" - ], - "Entities": [ - "version-0.105.0-entity_index", - "version-0.105.0-entity_air_quality", - "version-0.105.0-entity_alarm_control_panel", - "version-0.105.0-entity_binary_sensor", - "version-0.105.0-entity_climate", - "version-0.105.0-entity_cover", - "version-0.105.0-entity_fan", - "version-0.105.0-entity_light", - "version-0.105.0-entity_lock", - "version-0.105.0-entity_media_player", - "version-0.105.0-entity_remote", - "version-0.105.0-entity_sensor", - "version-0.105.0-entity_switch", - "version-0.105.0-entity_vacuum", - "version-0.105.0-entity_water_heater", - "version-0.105.0-entity_weather" - ], - "Authentication": [ - "version-0.105.0-auth_index", - "version-0.105.0-auth_permissions", - "version-0.105.0-auth_api", - "version-0.105.0-auth_auth_provider", - "version-0.105.0-auth_auth_module" - ], - "Config Entries": [ - "version-0.105.0-config_entries_index" - ], - "Data Entry Flow": [ - "version-0.105.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.105.0-entity_registry_index", - "version-0.105.0-entity_registry_disabled_by" - ], - "Device Registry": [ - "version-0.105.0-device_registry_index" - ], - "Area Registry": [ - "version-0.105.0-area_registry_index" - ] - }, - "version-0.105.0-Extending Frontend": { - "Frontend": [ - "version-0.105.0-frontend_index", - "version-0.105.0-frontend_architecture", - "version-0.105.0-frontend_development", - "version-0.105.0-frontend_data", - "version-0.105.0-frontend_external_auth", - "version-0.105.0-frontend_external_bus" - ], - "Extending the frontend": [ - "version-0.105.0-frontend_add_card", - "version-0.105.0-frontend_add_more_info", - "version-0.105.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.105.0-lovelace_custom_card", - "version-0.105.0-frontend_creating_custom_panels" - ] - }, - "version-0.105.0-Extending Home Assistant": { - "Development Workflow": [ - "version-0.105.0-development_index", - "version-0.105.0-development_environment", - "version-0.105.0-development_submitting", - "version-0.105.0-development_guidelines", - "version-0.105.0-development_testing", - "version-0.105.0-development_catching_up" - ], - "Building Integrations": [ - "version-0.105.0-creating_integration_file_structure", - "version-0.105.0-creating_integration_manifest", - "version-0.105.0-creating_component_index", - "version-0.105.0-config_entries_config_flow_handler", - "version-0.105.0-config_entries_options_flow_handler", - "version-0.105.0-configuration_yaml_index", - "version-0.105.0-dev_101_services", - "version-0.105.0-creating_platform_index", - "version-0.105.0-creating_component_generic_discovery", - "version-0.105.0-reproduce_state_index", - "version-0.105.0-integration_fetching_data" - ], - "Development Checklist": [ - "version-0.105.0-development_checklist", - "version-0.105.0-creating_component_code_review", - "version-0.105.0-creating_platform_code_review", - "version-0.105.0-integration_quality_scale_index" - ], - "Home Assistant Core 101": [ - "version-0.105.0-dev_101_index", - "version-0.105.0-dev_101_hass", - "version-0.105.0-dev_101_events", - "version-0.105.0-dev_101_states", - "version-0.105.0-dev_101_config" - ], - "Device Automations": [ - "version-0.105.0-device_automation_index", - "version-0.105.0-device_automation_trigger", - "version-0.105.0-device_automation_condition", - "version-0.105.0-device_automation_action" - ], - "Misc": [ - "version-0.105.0-development_validation", - "version-0.105.0-development_typing" - ] - }, - "version-0.105.0-Misc": { - "Introduction": [ - "version-0.105.0-misc" - ], - "External API": [ - "version-0.105.0-external_api_rest", - "version-0.105.0-external_api_rest_python", - "version-0.105.0-external_api_websocket", - "version-0.105.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.105.0-internationalization_index", - "version-0.105.0-internationalization_backend_localization", - "version-0.105.0-internationalization_custom_component_localization", - "version-0.105.0-internationalization_translation" - ], - "Documentation": [ - "version-0.105.0-documentation_index", - "version-0.105.0-documentation_standards", - "version-0.105.0-documentation_create_page" - ], - "Intents": [ - "version-0.105.0-intent_index", - "version-0.105.0-intent_firing", - "version-0.105.0-intent_handling", - "version-0.105.0-intent_conversation", - "version-0.105.0-intent_builtin" - ], - "Native App Integration": [ - "version-0.105.0-app_integration_index", - "version-0.105.0-app_integration_setup", - "version-0.105.0-app_integration_sending_data", - "version-0.105.0-app_integration_sensors", - "version-0.105.0-app_integration_notifications", - "version-0.105.0-app_integration_webview" - ], - "Building a Python library": [ - "version-0.105.0-api_lib_index", - "version-0.105.0-api_lib_auth", - "version-0.105.0-api_lib_data_models" - ], - "asyncio": [ - "version-0.105.0-asyncio_index", - "version-0.105.0-asyncio_101", - "version-0.105.0-asyncio_categorizing_functions", - "version-0.105.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.105.0-hassio_debugging", - "version-0.105.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.105.0-hassio_addon_index", - "version-0.105.0-hassio_addon_tutorial", - "version-0.105.0-hassio_addon_config", - "version-0.105.0-hassio_addon_communication", - "version-0.105.0-hassio_addon_testing", - "version-0.105.0-hassio_addon_publishing", - "version-0.105.0-hassio_addon_presentation", - "version-0.105.0-hassio_addon_repository", - "version-0.105.0-hassio_addon_security" - ], - "Maintainer docs": [ - "version-0.105.0-maintenance", - "version-0.105.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.72-sidebars.json b/website/versioned_sidebars/version-0.72-sidebars.json deleted file mode 100644 index 71329779..00000000 --- a/website/versioned_sidebars/version-0.72-sidebars.json +++ /dev/null @@ -1,150 +0,0 @@ -{ - "version-0.72-Architecture": { - "Architecture": [ - "version-0.72-architecture_index", - "version-0.72-architecture_components", - "version-0.72-architecture_entities", - "version-0.72-architecture_hassio" - ], - "Entities": [ - "version-0.72-entity_index", - "version-0.72-entity_alarm_control_panel", - "version-0.72-entity_binary_sensor", - "version-0.72-entity_climate", - "version-0.72-entity_cover", - "version-0.72-entity_fan", - "version-0.72-entity_light", - "version-0.72-entity_lock", - "version-0.72-entity_media_player", - "version-0.72-entity_remote", - "version-0.72-entity_sensor", - "version-0.72-entity_switch", - "version-0.72-entity_vacuum", - "version-0.72-entity_weather" - ], - "Authentication": [ - "version-0.72-auth_index", - "version-0.72-auth_api", - "version-0.72-auth_auth_provider" - ], - "Configuration.yaml": [ - "version-0.72-configuration_yaml_index" - ], - "Config Entries": [ - "version-0.72-config_entries_index", - "version-0.72-config_entries_config_flow_handler" - ], - "Data Entry Flow": [ - "version-0.72-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.72-entity_registry_index" - ] - }, - "version-0.72-Extending Frontend": { - "Frontend": [ - "version-0.72-frontend_index", - "version-0.72-frontend_architecture", - "version-0.72-frontend_development" - ], - "Extending the frontend": [ - "version-0.72-frontend_add_card", - "version-0.72-frontend_add_more_info", - "version-0.72-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.72-frontend_creating_custom_ui", - "version-0.72-frontend_creating_custom_panels" - ], - "Lovelace UI": [ - "version-0.72-lovelace_index", - "version-0.72-lovelace_card_types", - "version-0.72-lovelace_custom_card" - ] - }, - "version-0.72-Extending HASS": { - "Developing a feature": [ - "version-0.72-development_index", - "version-0.72-development_environment", - "version-0.72-development_submitting", - "version-0.72-development_checklist", - "version-0.72-development_guidelines", - "version-0.72-development_testing", - "version-0.72-development_catching_up", - "version-0.72-development_validation", - "version-0.72-development_typing" - ], - "Development 101": [ - "version-0.72-dev_101_index", - "version-0.72-dev_101_hass", - "version-0.72-dev_101_events", - "version-0.72-dev_101_states", - "version-0.72-dev_101_services", - "version-0.72-dev_101_config" - ], - "Creating Platforms": [ - "version-0.72-creating_platform_index", - "version-0.72-creating_platform_code_review", - "version-0.72-creating_platform_example_light", - "version-0.72-creating_platform_example_sensor" - ], - "Creating Components": [ - "version-0.72-creating_component_index", - "version-0.72-creating_component_code_review", - "version-0.72-creating_component_deps_and_reqs", - "version-0.72-creating_component_events", - "version-0.72-creating_component_states", - "version-0.72-creating_component_discovery", - "version-0.72-creating_component_loading", - "version-0.72-creating_component_generic_discovery" - ] - }, - "version-0.72-Misc": { - "Introduction": [ - "version-0.72-misc" - ], - "External API": [ - "version-0.72-external_api_rest", - "version-0.72-external_api_rest_python", - "version-0.72-external_api_websocket", - "version-0.72-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.72-internationalization_index", - "version-0.72-internationalization_backend_localization", - "version-0.72-internationalization_custom_component_localization", - "version-0.72-internationalization_translation" - ], - "Intents": [ - "version-0.72-intent_index", - "version-0.72-intent_firing", - "version-0.72-intent_handling", - "version-0.72-intent_conversation", - "version-0.72-intent_builtin" - ], - "asyncio": [ - "version-0.72-asyncio_index", - "version-0.72-asyncio_101", - "version-0.72-asyncio_categorizing_functions", - "version-0.72-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.72-hassio_debugging", - "version-0.72-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.72-hassio_addon_index", - "version-0.72-hassio_addon_tutorial", - "version-0.72-hassio_addon_config", - "version-0.72-hassio_addon_communication", - "version-0.72-hassio_addon_testing", - "version-0.72-hassio_addon_publishing", - "version-0.72-hassio_addon_presentation", - "version-0.72-hassio_addon_repository" - ], - "Maintainer docs": [ - "version-0.72-maintenance", - "version-0.72-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.73.0-sidebars.json b/website/versioned_sidebars/version-0.73.0-sidebars.json deleted file mode 100644 index 4e02840a..00000000 --- a/website/versioned_sidebars/version-0.73.0-sidebars.json +++ /dev/null @@ -1,154 +0,0 @@ -{ - "version-0.73.0-Architecture": { - "Architecture": [ - "version-0.73.0-architecture_index", - "version-0.73.0-architecture_components", - "version-0.73.0-architecture_entities", - "version-0.73.0-architecture_hassio" - ], - "Entities": [ - "version-0.73.0-entity_index", - "version-0.73.0-entity_alarm_control_panel", - "version-0.73.0-entity_binary_sensor", - "version-0.73.0-entity_climate", - "version-0.73.0-entity_cover", - "version-0.73.0-entity_fan", - "version-0.73.0-entity_light", - "version-0.73.0-entity_lock", - "version-0.73.0-entity_media_player", - "version-0.73.0-entity_remote", - "version-0.73.0-entity_sensor", - "version-0.73.0-entity_switch", - "version-0.73.0-entity_vacuum", - "version-0.73.0-entity_weather" - ], - "Authentication": [ - "version-0.73.0-auth_index", - "version-0.73.0-auth_api", - "version-0.73.0-auth_auth_provider" - ], - "Configuration.yaml": [ - "version-0.73.0-configuration_yaml_index" - ], - "Config Entries": [ - "version-0.73.0-config_entries_index", - "version-0.73.0-config_entries_config_flow_handler" - ], - "Data Entry Flow": [ - "version-0.73.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.73.0-entity_registry_index" - ] - }, - "version-0.73.0-Extending Frontend": { - "Frontend": [ - "version-0.73.0-frontend_index", - "version-0.73.0-frontend_architecture", - "version-0.73.0-frontend_development" - ], - "Extending the frontend": [ - "version-0.73.0-frontend_add_card", - "version-0.73.0-frontend_add_more_info", - "version-0.73.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.73.0-frontend_creating_custom_ui", - "version-0.73.0-frontend_creating_custom_panels" - ], - "Lovelace UI": [ - "version-0.73.0-lovelace_index", - "version-0.73.0-lovelace_custom_card" - ] - }, - "version-0.73.0-Extending HASS": { - "Developing a feature": [ - "version-0.73.0-development_index", - "version-0.73.0-development_environment", - "version-0.73.0-development_submitting", - "version-0.73.0-development_checklist", - "version-0.73.0-development_guidelines", - "version-0.73.0-development_testing", - "version-0.73.0-development_catching_up", - "version-0.73.0-development_validation", - "version-0.73.0-development_typing" - ], - "Development 101": [ - "version-0.73.0-dev_101_index", - "version-0.73.0-dev_101_hass", - "version-0.73.0-dev_101_events", - "version-0.73.0-dev_101_states", - "version-0.73.0-dev_101_services", - "version-0.73.0-dev_101_config" - ], - "Creating Platforms": [ - "version-0.73.0-creating_platform_index", - "version-0.73.0-creating_platform_code_review", - "version-0.73.0-creating_platform_example_light", - "version-0.73.0-creating_platform_example_sensor" - ], - "Creating Components": [ - "version-0.73.0-creating_component_index", - "version-0.73.0-creating_component_code_review", - "version-0.73.0-creating_component_deps_and_reqs", - "version-0.73.0-creating_component_events", - "version-0.73.0-creating_component_states", - "version-0.73.0-creating_component_discovery", - "version-0.73.0-creating_component_loading", - "version-0.73.0-creating_component_generic_discovery" - ] - }, - "version-0.73.0-Misc": { - "Introduction": [ - "version-0.73.0-misc" - ], - "External API": [ - "version-0.73.0-external_api_rest", - "version-0.73.0-external_api_rest_python", - "version-0.73.0-external_api_websocket", - "version-0.73.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.73.0-internationalization_index", - "version-0.73.0-internationalization_backend_localization", - "version-0.73.0-internationalization_custom_component_localization", - "version-0.73.0-internationalization_translation" - ], - "Documentation": [ - "version-0.73.0-documentation_index", - "version-0.73.0-documentation_standards", - "version-0.73.0-documentation_create_page" - ], - "Intents": [ - "version-0.73.0-intent_index", - "version-0.73.0-intent_firing", - "version-0.73.0-intent_handling", - "version-0.73.0-intent_conversation", - "version-0.73.0-intent_builtin" - ], - "asyncio": [ - "version-0.73.0-asyncio_index", - "version-0.73.0-asyncio_101", - "version-0.73.0-asyncio_categorizing_functions", - "version-0.73.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.73.0-hassio_debugging", - "version-0.73.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.73.0-hassio_addon_index", - "version-0.73.0-hassio_addon_tutorial", - "version-0.73.0-hassio_addon_config", - "version-0.73.0-hassio_addon_communication", - "version-0.73.0-hassio_addon_testing", - "version-0.73.0-hassio_addon_publishing", - "version-0.73.0-hassio_addon_presentation", - "version-0.73.0-hassio_addon_repository" - ], - "Maintainer docs": [ - "version-0.73.0-maintenance", - "version-0.73.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.74.0-sidebars.json b/website/versioned_sidebars/version-0.74.0-sidebars.json deleted file mode 100644 index 7bcd4676..00000000 --- a/website/versioned_sidebars/version-0.74.0-sidebars.json +++ /dev/null @@ -1,151 +0,0 @@ -{ - "version-0.74.0-Architecture": { - "Architecture": [ - "version-0.74.0-architecture_index", - "version-0.74.0-architecture_components", - "version-0.74.0-architecture_entities", - "version-0.74.0-architecture_hassio" - ], - "Entities": [ - "version-0.74.0-entity_index", - "version-0.74.0-entity_alarm_control_panel", - "version-0.74.0-entity_binary_sensor", - "version-0.74.0-entity_climate", - "version-0.74.0-entity_cover", - "version-0.74.0-entity_fan", - "version-0.74.0-entity_light", - "version-0.74.0-entity_lock", - "version-0.74.0-entity_media_player", - "version-0.74.0-entity_remote", - "version-0.74.0-entity_sensor", - "version-0.74.0-entity_switch", - "version-0.74.0-entity_vacuum", - "version-0.74.0-entity_weather" - ], - "Authentication": [ - "version-0.74.0-auth_index", - "version-0.74.0-auth_api", - "version-0.74.0-auth_auth_provider" - ], - "Configuration.yaml": [ - "version-0.74.0-configuration_yaml_index" - ], - "Config Entries": [ - "version-0.74.0-config_entries_index", - "version-0.74.0-config_entries_config_flow_handler" - ], - "Data Entry Flow": [ - "version-0.74.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.74.0-entity_registry_index" - ] - }, - "version-0.74.0-Extending Frontend": { - "Frontend": [ - "version-0.74.0-frontend_index", - "version-0.74.0-frontend_architecture", - "version-0.74.0-frontend_development" - ], - "Extending the frontend": [ - "version-0.74.0-frontend_add_card", - "version-0.74.0-frontend_add_more_info", - "version-0.74.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.74.0-lovelace_custom_card", - "version-0.74.0-frontend_creating_custom_ui", - "version-0.74.0-frontend_creating_custom_panels" - ] - }, - "version-0.74.0-Extending HASS": { - "Developing a feature": [ - "version-0.74.0-development_index", - "version-0.74.0-development_environment", - "version-0.74.0-development_submitting", - "version-0.74.0-development_checklist", - "version-0.74.0-development_guidelines", - "version-0.74.0-development_testing", - "version-0.74.0-development_catching_up", - "version-0.74.0-development_validation", - "version-0.74.0-development_typing" - ], - "Development 101": [ - "version-0.74.0-dev_101_index", - "version-0.74.0-dev_101_hass", - "version-0.74.0-dev_101_events", - "version-0.74.0-dev_101_states", - "version-0.74.0-dev_101_services", - "version-0.74.0-dev_101_config" - ], - "Creating Platforms": [ - "version-0.74.0-creating_platform_index", - "version-0.74.0-creating_platform_code_review", - "version-0.74.0-creating_platform_example_light", - "version-0.74.0-creating_platform_example_sensor" - ], - "Creating Components": [ - "version-0.74.0-creating_component_index", - "version-0.74.0-creating_component_code_review", - "version-0.74.0-creating_component_deps_and_reqs", - "version-0.74.0-creating_component_events", - "version-0.74.0-creating_component_states", - "version-0.74.0-creating_component_discovery", - "version-0.74.0-creating_component_loading", - "version-0.74.0-creating_component_generic_discovery" - ] - }, - "version-0.74.0-Misc": { - "Introduction": [ - "version-0.74.0-misc" - ], - "External API": [ - "version-0.74.0-external_api_rest", - "version-0.74.0-external_api_rest_python", - "version-0.74.0-external_api_websocket", - "version-0.74.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.74.0-internationalization_index", - "version-0.74.0-internationalization_backend_localization", - "version-0.74.0-internationalization_custom_component_localization", - "version-0.74.0-internationalization_translation" - ], - "Documentation": [ - "version-0.74.0-documentation_index", - "version-0.74.0-documentation_standards", - "version-0.74.0-documentation_create_page" - ], - "Intents": [ - "version-0.74.0-intent_index", - "version-0.74.0-intent_firing", - "version-0.74.0-intent_handling", - "version-0.74.0-intent_conversation", - "version-0.74.0-intent_builtin" - ], - "asyncio": [ - "version-0.74.0-asyncio_index", - "version-0.74.0-asyncio_101", - "version-0.74.0-asyncio_categorizing_functions", - "version-0.74.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.74.0-hassio_debugging", - "version-0.74.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.74.0-hassio_addon_index", - "version-0.74.0-hassio_addon_tutorial", - "version-0.74.0-hassio_addon_config", - "version-0.74.0-hassio_addon_communication", - "version-0.74.0-hassio_addon_testing", - "version-0.74.0-hassio_addon_publishing", - "version-0.74.0-hassio_addon_presentation", - "version-0.74.0-hassio_addon_repository" - ], - "Maintainer docs": [ - "version-0.74.0-maintenance", - "version-0.74.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.76.0-sidebars.json b/website/versioned_sidebars/version-0.76.0-sidebars.json deleted file mode 100644 index 0df8307a..00000000 --- a/website/versioned_sidebars/version-0.76.0-sidebars.json +++ /dev/null @@ -1,152 +0,0 @@ -{ - "version-0.76.0-Architecture": { - "Architecture": [ - "version-0.76.0-architecture_index", - "version-0.76.0-architecture_components", - "version-0.76.0-architecture_entities", - "version-0.76.0-architecture_hassio" - ], - "Entities": [ - "version-0.76.0-entity_index", - "version-0.76.0-entity_alarm_control_panel", - "version-0.76.0-entity_binary_sensor", - "version-0.76.0-entity_climate", - "version-0.76.0-entity_cover", - "version-0.76.0-entity_fan", - "version-0.76.0-entity_light", - "version-0.76.0-entity_lock", - "version-0.76.0-entity_media_player", - "version-0.76.0-entity_remote", - "version-0.76.0-entity_sensor", - "version-0.76.0-entity_switch", - "version-0.76.0-entity_vacuum", - "version-0.76.0-entity_weather" - ], - "Authentication": [ - "version-0.76.0-auth_index", - "version-0.76.0-auth_api", - "version-0.76.0-auth_auth_provider" - ], - "Configuration.yaml": [ - "version-0.76.0-configuration_yaml_index" - ], - "Config Entries": [ - "version-0.76.0-config_entries_index", - "version-0.76.0-config_entries_config_flow_handler" - ], - "Data Entry Flow": [ - "version-0.76.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.76.0-entity_registry_index" - ] - }, - "version-0.76.0-Extending Frontend": { - "Frontend": [ - "version-0.76.0-frontend_index", - "version-0.76.0-frontend_architecture", - "version-0.76.0-frontend_development", - "version-0.76.0-frontend_data" - ], - "Extending the frontend": [ - "version-0.76.0-frontend_add_card", - "version-0.76.0-frontend_add_more_info", - "version-0.76.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.76.0-lovelace_custom_card", - "version-0.76.0-frontend_creating_custom_ui", - "version-0.76.0-frontend_creating_custom_panels" - ] - }, - "version-0.76.0-Extending HASS": { - "Developing a feature": [ - "version-0.76.0-development_index", - "version-0.76.0-development_environment", - "version-0.76.0-development_submitting", - "version-0.76.0-development_checklist", - "version-0.76.0-development_guidelines", - "version-0.76.0-development_testing", - "version-0.76.0-development_catching_up", - "version-0.76.0-development_validation", - "version-0.76.0-development_typing" - ], - "Development 101": [ - "version-0.76.0-dev_101_index", - "version-0.76.0-dev_101_hass", - "version-0.76.0-dev_101_events", - "version-0.76.0-dev_101_states", - "version-0.76.0-dev_101_services", - "version-0.76.0-dev_101_config" - ], - "Creating Platforms": [ - "version-0.76.0-creating_platform_index", - "version-0.76.0-creating_platform_code_review", - "version-0.76.0-creating_platform_example_light", - "version-0.76.0-creating_platform_example_sensor" - ], - "Creating Components": [ - "version-0.76.0-creating_component_index", - "version-0.76.0-creating_component_code_review", - "version-0.76.0-creating_component_deps_and_reqs", - "version-0.76.0-creating_component_events", - "version-0.76.0-creating_component_states", - "version-0.76.0-creating_component_discovery", - "version-0.76.0-creating_component_loading", - "version-0.76.0-creating_component_generic_discovery" - ] - }, - "version-0.76.0-Misc": { - "Introduction": [ - "version-0.76.0-misc" - ], - "External API": [ - "version-0.76.0-external_api_rest", - "version-0.76.0-external_api_rest_python", - "version-0.76.0-external_api_websocket", - "version-0.76.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.76.0-internationalization_index", - "version-0.76.0-internationalization_backend_localization", - "version-0.76.0-internationalization_custom_component_localization", - "version-0.76.0-internationalization_translation" - ], - "Documentation": [ - "version-0.76.0-documentation_index", - "version-0.76.0-documentation_standards", - "version-0.76.0-documentation_create_page" - ], - "Intents": [ - "version-0.76.0-intent_index", - "version-0.76.0-intent_firing", - "version-0.76.0-intent_handling", - "version-0.76.0-intent_conversation", - "version-0.76.0-intent_builtin" - ], - "asyncio": [ - "version-0.76.0-asyncio_index", - "version-0.76.0-asyncio_101", - "version-0.76.0-asyncio_categorizing_functions", - "version-0.76.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.76.0-hassio_debugging", - "version-0.76.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.76.0-hassio_addon_index", - "version-0.76.0-hassio_addon_tutorial", - "version-0.76.0-hassio_addon_config", - "version-0.76.0-hassio_addon_communication", - "version-0.76.0-hassio_addon_testing", - "version-0.76.0-hassio_addon_publishing", - "version-0.76.0-hassio_addon_presentation", - "version-0.76.0-hassio_addon_repository" - ], - "Maintainer docs": [ - "version-0.76.0-maintenance", - "version-0.76.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.77.0-sidebars.json b/website/versioned_sidebars/version-0.77.0-sidebars.json deleted file mode 100644 index 4f4c9426..00000000 --- a/website/versioned_sidebars/version-0.77.0-sidebars.json +++ /dev/null @@ -1,153 +0,0 @@ -{ - "version-0.77.0-Architecture": { - "Architecture": [ - "version-0.77.0-architecture_index", - "version-0.77.0-architecture_components", - "version-0.77.0-architecture_entities", - "version-0.77.0-architecture_hassio" - ], - "Entities": [ - "version-0.77.0-entity_index", - "version-0.77.0-entity_alarm_control_panel", - "version-0.77.0-entity_binary_sensor", - "version-0.77.0-entity_climate", - "version-0.77.0-entity_cover", - "version-0.77.0-entity_fan", - "version-0.77.0-entity_light", - "version-0.77.0-entity_lock", - "version-0.77.0-entity_media_player", - "version-0.77.0-entity_remote", - "version-0.77.0-entity_sensor", - "version-0.77.0-entity_switch", - "version-0.77.0-entity_vacuum", - "version-0.77.0-entity_weather" - ], - "Authentication": [ - "version-0.77.0-auth_index", - "version-0.77.0-auth_api", - "version-0.77.0-auth_auth_provider", - "version-0.77.0-auth_auth_module" - ], - "Configuration.yaml": [ - "version-0.77.0-configuration_yaml_index" - ], - "Config Entries": [ - "version-0.77.0-config_entries_index", - "version-0.77.0-config_entries_config_flow_handler" - ], - "Data Entry Flow": [ - "version-0.77.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.77.0-entity_registry_index" - ] - }, - "version-0.77.0-Extending Frontend": { - "Frontend": [ - "version-0.77.0-frontend_index", - "version-0.77.0-frontend_architecture", - "version-0.77.0-frontend_development", - "version-0.77.0-frontend_data" - ], - "Extending the frontend": [ - "version-0.77.0-frontend_add_card", - "version-0.77.0-frontend_add_more_info", - "version-0.77.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.77.0-lovelace_custom_card", - "version-0.77.0-frontend_creating_custom_ui", - "version-0.77.0-frontend_creating_custom_panels" - ] - }, - "version-0.77.0-Extending HASS": { - "Developing a feature": [ - "version-0.77.0-development_index", - "version-0.77.0-development_environment", - "version-0.77.0-development_submitting", - "version-0.77.0-development_checklist", - "version-0.77.0-development_guidelines", - "version-0.77.0-development_testing", - "version-0.77.0-development_catching_up", - "version-0.77.0-development_validation", - "version-0.77.0-development_typing" - ], - "Development 101": [ - "version-0.77.0-dev_101_index", - "version-0.77.0-dev_101_hass", - "version-0.77.0-dev_101_events", - "version-0.77.0-dev_101_states", - "version-0.77.0-dev_101_services", - "version-0.77.0-dev_101_config" - ], - "Creating Platforms": [ - "version-0.77.0-creating_platform_index", - "version-0.77.0-creating_platform_code_review", - "version-0.77.0-creating_platform_example_light", - "version-0.77.0-creating_platform_example_sensor" - ], - "Creating Components": [ - "version-0.77.0-creating_component_index", - "version-0.77.0-creating_component_code_review", - "version-0.77.0-creating_component_deps_and_reqs", - "version-0.77.0-creating_component_events", - "version-0.77.0-creating_component_states", - "version-0.77.0-creating_component_discovery", - "version-0.77.0-creating_component_loading", - "version-0.77.0-creating_component_generic_discovery" - ] - }, - "version-0.77.0-Misc": { - "Introduction": [ - "version-0.77.0-misc" - ], - "External API": [ - "version-0.77.0-external_api_rest", - "version-0.77.0-external_api_rest_python", - "version-0.77.0-external_api_websocket", - "version-0.77.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.77.0-internationalization_index", - "version-0.77.0-internationalization_backend_localization", - "version-0.77.0-internationalization_custom_component_localization", - "version-0.77.0-internationalization_translation" - ], - "Documentation": [ - "version-0.77.0-documentation_index", - "version-0.77.0-documentation_standards", - "version-0.77.0-documentation_create_page" - ], - "Intents": [ - "version-0.77.0-intent_index", - "version-0.77.0-intent_firing", - "version-0.77.0-intent_handling", - "version-0.77.0-intent_conversation", - "version-0.77.0-intent_builtin" - ], - "asyncio": [ - "version-0.77.0-asyncio_index", - "version-0.77.0-asyncio_101", - "version-0.77.0-asyncio_categorizing_functions", - "version-0.77.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.77.0-hassio_debugging", - "version-0.77.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.77.0-hassio_addon_index", - "version-0.77.0-hassio_addon_tutorial", - "version-0.77.0-hassio_addon_config", - "version-0.77.0-hassio_addon_communication", - "version-0.77.0-hassio_addon_testing", - "version-0.77.0-hassio_addon_publishing", - "version-0.77.0-hassio_addon_presentation", - "version-0.77.0-hassio_addon_repository" - ], - "Maintainer docs": [ - "version-0.77.0-maintenance", - "version-0.77.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.78.0-sidebars.json b/website/versioned_sidebars/version-0.78.0-sidebars.json deleted file mode 100644 index ed49f725..00000000 --- a/website/versioned_sidebars/version-0.78.0-sidebars.json +++ /dev/null @@ -1,158 +0,0 @@ -{ - "version-0.78.0-Architecture": { - "Architecture": [ - "version-0.78.0-architecture_index", - "version-0.78.0-architecture_components", - "version-0.78.0-architecture_entities", - "version-0.78.0-architecture_hassio" - ], - "Entities": [ - "version-0.78.0-entity_index", - "version-0.78.0-entity_alarm_control_panel", - "version-0.78.0-entity_binary_sensor", - "version-0.78.0-entity_climate", - "version-0.78.0-entity_cover", - "version-0.78.0-entity_fan", - "version-0.78.0-entity_light", - "version-0.78.0-entity_lock", - "version-0.78.0-entity_media_player", - "version-0.78.0-entity_remote", - "version-0.78.0-entity_sensor", - "version-0.78.0-entity_switch", - "version-0.78.0-entity_vacuum", - "version-0.78.0-entity_weather" - ], - "Authentication": [ - "version-0.78.0-auth_index", - "version-0.78.0-auth_api", - "version-0.78.0-auth_auth_provider", - "version-0.78.0-auth_auth_module" - ], - "Configuration.yaml": [ - "version-0.78.0-configuration_yaml_index" - ], - "Config Entries": [ - "version-0.78.0-config_entries_index", - "version-0.78.0-config_entries_config_flow_handler" - ], - "Data Entry Flow": [ - "version-0.78.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.78.0-entity_registry_index" - ], - "Device Registry": [ - "version-0.78.0-device_registry_index" - ] - }, - "version-0.78.0-Extending Frontend": { - "Frontend": [ - "version-0.78.0-frontend_index", - "version-0.78.0-frontend_architecture", - "version-0.78.0-frontend_development", - "version-0.78.0-frontend_data", - "version-0.78.0-frontend_external_auth" - ], - "Extending the frontend": [ - "version-0.78.0-frontend_add_card", - "version-0.78.0-frontend_add_more_info", - "version-0.78.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.78.0-lovelace_custom_card", - "version-0.78.0-frontend_creating_custom_ui", - "version-0.78.0-frontend_creating_custom_panels" - ] - }, - "version-0.78.0-Extending HASS": { - "Developing a feature": [ - "version-0.78.0-development_index", - "version-0.78.0-development_environment", - "version-0.78.0-development_submitting", - "version-0.78.0-development_checklist", - "version-0.78.0-development_guidelines", - "version-0.78.0-development_testing", - "version-0.78.0-development_catching_up", - "version-0.78.0-development_validation", - "version-0.78.0-development_typing" - ], - "Development 101": [ - "version-0.78.0-dev_101_index", - "version-0.78.0-dev_101_hass", - "version-0.78.0-dev_101_events", - "version-0.78.0-dev_101_states", - "version-0.78.0-dev_101_services", - "version-0.78.0-dev_101_config" - ], - "Creating Platforms": [ - "version-0.78.0-creating_platform_index", - "version-0.78.0-creating_platform_code_review", - "version-0.78.0-creating_platform_example_light", - "version-0.78.0-creating_platform_example_sensor" - ], - "Creating Components": [ - "version-0.78.0-creating_component_index", - "version-0.78.0-creating_component_code_review", - "version-0.78.0-creating_component_deps_and_reqs", - "version-0.78.0-creating_component_events", - "version-0.78.0-creating_component_states", - "version-0.78.0-creating_component_discovery", - "version-0.78.0-creating_component_loading", - "version-0.78.0-creating_component_generic_discovery" - ] - }, - "version-0.78.0-Misc": { - "Introduction": [ - "version-0.78.0-misc" - ], - "External API": [ - "version-0.78.0-external_api_rest", - "version-0.78.0-external_api_rest_python", - "version-0.78.0-external_api_websocket", - "version-0.78.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.78.0-internationalization_index", - "version-0.78.0-internationalization_backend_localization", - "version-0.78.0-internationalization_custom_component_localization", - "version-0.78.0-internationalization_translation" - ], - "Documentation": [ - "version-0.78.0-documentation_index", - "version-0.78.0-documentation_standards", - "version-0.78.0-documentation_create_page" - ], - "Intents": [ - "version-0.78.0-intent_index", - "version-0.78.0-intent_firing", - "version-0.78.0-intent_handling", - "version-0.78.0-intent_conversation", - "version-0.78.0-intent_builtin" - ], - "asyncio": [ - "version-0.78.0-asyncio_index", - "version-0.78.0-asyncio_101", - "version-0.78.0-asyncio_categorizing_functions", - "version-0.78.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.78.0-hassio_debugging", - "version-0.78.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.78.0-hassio_addon_index", - "version-0.78.0-hassio_addon_tutorial", - "version-0.78.0-hassio_addon_config", - "version-0.78.0-hassio_addon_communication", - "version-0.78.0-hassio_addon_testing", - "version-0.78.0-hassio_addon_publishing", - "version-0.78.0-hassio_addon_presentation", - "version-0.78.0-hassio_addon_repository", - "version-0.78.0-hassio_addon_security" - ], - "Maintainer docs": [ - "version-0.78.0-maintenance", - "version-0.78.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.79.0-sidebars.json b/website/versioned_sidebars/version-0.79.0-sidebars.json deleted file mode 100644 index 7270f1d1..00000000 --- a/website/versioned_sidebars/version-0.79.0-sidebars.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "version-0.79.0-Architecture": { - "Architecture": [ - "version-0.79.0-architecture_index", - "version-0.79.0-architecture_components", - "version-0.79.0-architecture_entities", - "version-0.79.0-architecture_hassio" - ], - "Entities": [ - "version-0.79.0-entity_index", - "version-0.79.0-entity_alarm_control_panel", - "version-0.79.0-entity_binary_sensor", - "version-0.79.0-entity_climate", - "version-0.79.0-entity_cover", - "version-0.79.0-entity_fan", - "version-0.79.0-entity_light", - "version-0.79.0-entity_lock", - "version-0.79.0-entity_media_player", - "version-0.79.0-entity_remote", - "version-0.79.0-entity_sensor", - "version-0.79.0-entity_switch", - "version-0.79.0-entity_vacuum", - "version-0.79.0-entity_weather" - ], - "Authentication": [ - "version-0.79.0-auth_index", - "version-0.79.0-auth_api", - "version-0.79.0-auth_auth_provider", - "version-0.79.0-auth_auth_module" - ], - "Configuration.yaml": [ - "version-0.79.0-configuration_yaml_index" - ], - "Config Entries": [ - "version-0.79.0-config_entries_index", - "version-0.79.0-config_entries_config_flow_handler" - ], - "Data Entry Flow": [ - "version-0.79.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.79.0-entity_registry_index" - ], - "Device Registry": [ - "version-0.79.0-device_registry_index" - ] - }, - "version-0.79.0-Extending Frontend": { - "Frontend": [ - "version-0.79.0-frontend_index", - "version-0.79.0-frontend_architecture", - "version-0.79.0-frontend_development", - "version-0.79.0-frontend_data", - "version-0.79.0-frontend_external_auth" - ], - "Extending the frontend": [ - "version-0.79.0-frontend_add_card", - "version-0.79.0-frontend_add_more_info", - "version-0.79.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.79.0-lovelace_custom_card", - "version-0.79.0-frontend_creating_custom_ui", - "version-0.79.0-frontend_creating_custom_panels" - ] - }, - "version-0.79.0-Extending HASS": { - "Developing a feature": [ - "version-0.79.0-development_index", - "version-0.79.0-development_environment", - "version-0.79.0-development_submitting", - "version-0.79.0-development_checklist", - "version-0.79.0-development_guidelines", - "version-0.79.0-development_testing", - "version-0.79.0-development_catching_up", - "version-0.79.0-development_validation", - "version-0.79.0-development_typing" - ], - "Development 101": [ - "version-0.79.0-dev_101_index", - "version-0.79.0-dev_101_hass", - "version-0.79.0-dev_101_events", - "version-0.79.0-dev_101_states", - "version-0.79.0-dev_101_services", - "version-0.79.0-dev_101_config" - ], - "Integration Quality Scale": [ - "version-0.79.0-integration_quality_scale_index" - ], - "Creating Platforms": [ - "version-0.79.0-creating_platform_index", - "version-0.79.0-creating_platform_code_review", - "version-0.79.0-creating_platform_example_light", - "version-0.79.0-creating_platform_example_sensor" - ], - "Creating Components": [ - "version-0.79.0-creating_component_index", - "version-0.79.0-creating_component_code_review", - "version-0.79.0-creating_component_deps_and_reqs", - "version-0.79.0-creating_component_events", - "version-0.79.0-creating_component_states", - "version-0.79.0-creating_component_discovery", - "version-0.79.0-creating_component_loading", - "version-0.79.0-creating_component_generic_discovery" - ] - }, - "version-0.79.0-Misc": { - "Introduction": [ - "version-0.79.0-misc" - ], - "External API": [ - "version-0.79.0-external_api_rest", - "version-0.79.0-external_api_rest_python", - "version-0.79.0-external_api_websocket", - "version-0.79.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.79.0-internationalization_index", - "version-0.79.0-internationalization_backend_localization", - "version-0.79.0-internationalization_custom_component_localization", - "version-0.79.0-internationalization_translation" - ], - "Documentation": [ - "version-0.79.0-documentation_index", - "version-0.79.0-documentation_standards", - "version-0.79.0-documentation_create_page" - ], - "Intents": [ - "version-0.79.0-intent_index", - "version-0.79.0-intent_firing", - "version-0.79.0-intent_handling", - "version-0.79.0-intent_conversation", - "version-0.79.0-intent_builtin" - ], - "asyncio": [ - "version-0.79.0-asyncio_index", - "version-0.79.0-asyncio_101", - "version-0.79.0-asyncio_categorizing_functions", - "version-0.79.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.79.0-hassio_debugging", - "version-0.79.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.79.0-hassio_addon_index", - "version-0.79.0-hassio_addon_tutorial", - "version-0.79.0-hassio_addon_config", - "version-0.79.0-hassio_addon_communication", - "version-0.79.0-hassio_addon_testing", - "version-0.79.0-hassio_addon_publishing", - "version-0.79.0-hassio_addon_presentation", - "version-0.79.0-hassio_addon_repository", - "version-0.79.0-hassio_addon_security" - ], - "Maintainer docs": [ - "version-0.79.0-maintenance", - "version-0.79.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.80.0-sidebars.json b/website/versioned_sidebars/version-0.80.0-sidebars.json deleted file mode 100644 index 59257671..00000000 --- a/website/versioned_sidebars/version-0.80.0-sidebars.json +++ /dev/null @@ -1,163 +0,0 @@ -{ - "version-0.80.0-Architecture": { - "Architecture": [ - "version-0.80.0-architecture_index", - "version-0.80.0-architecture_components", - "version-0.80.0-architecture_entities", - "version-0.80.0-architecture_hassio" - ], - "Entities": [ - "version-0.80.0-entity_index", - "version-0.80.0-entity_alarm_control_panel", - "version-0.80.0-entity_binary_sensor", - "version-0.80.0-entity_climate", - "version-0.80.0-entity_cover", - "version-0.80.0-entity_fan", - "version-0.80.0-entity_light", - "version-0.80.0-entity_lock", - "version-0.80.0-entity_media_player", - "version-0.80.0-entity_remote", - "version-0.80.0-entity_sensor", - "version-0.80.0-entity_switch", - "version-0.80.0-entity_vacuum", - "version-0.80.0-entity_water_heater", - "version-0.80.0-entity_weather" - ], - "Authentication": [ - "version-0.80.0-auth_index", - "version-0.80.0-auth_permissions", - "version-0.80.0-auth_api", - "version-0.80.0-auth_auth_provider", - "version-0.80.0-auth_auth_module" - ], - "Configuration.yaml": [ - "version-0.80.0-configuration_yaml_index" - ], - "Config Entries": [ - "version-0.80.0-config_entries_index", - "version-0.80.0-config_entries_config_flow_handler" - ], - "Data Entry Flow": [ - "version-0.80.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.80.0-entity_registry_index" - ], - "Device Registry": [ - "version-0.80.0-device_registry_index" - ] - }, - "version-0.80.0-Extending Frontend": { - "Frontend": [ - "version-0.80.0-frontend_index", - "version-0.80.0-frontend_architecture", - "version-0.80.0-frontend_development", - "version-0.80.0-frontend_data", - "version-0.80.0-frontend_external_auth" - ], - "Extending the frontend": [ - "version-0.80.0-frontend_add_card", - "version-0.80.0-frontend_add_more_info", - "version-0.80.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.80.0-lovelace_custom_card", - "version-0.80.0-frontend_creating_custom_ui", - "version-0.80.0-frontend_creating_custom_panels" - ] - }, - "version-0.80.0-Extending HASS": { - "Developing a feature": [ - "version-0.80.0-development_index", - "version-0.80.0-development_environment", - "version-0.80.0-development_submitting", - "version-0.80.0-development_checklist", - "version-0.80.0-development_guidelines", - "version-0.80.0-development_testing", - "version-0.80.0-development_catching_up", - "version-0.80.0-development_validation", - "version-0.80.0-development_typing" - ], - "Development 101": [ - "version-0.80.0-dev_101_index", - "version-0.80.0-dev_101_hass", - "version-0.80.0-dev_101_events", - "version-0.80.0-dev_101_states", - "version-0.80.0-dev_101_services", - "version-0.80.0-dev_101_config" - ], - "Integration Quality Scale": [ - "version-0.80.0-integration_quality_scale_index" - ], - "Creating Platforms": [ - "version-0.80.0-creating_platform_index", - "version-0.80.0-creating_platform_code_review", - "version-0.80.0-creating_platform_example_light", - "version-0.80.0-creating_platform_example_sensor" - ], - "Creating Components": [ - "version-0.80.0-creating_component_index", - "version-0.80.0-creating_component_code_review", - "version-0.80.0-creating_component_deps_and_reqs", - "version-0.80.0-creating_component_events", - "version-0.80.0-creating_component_states", - "version-0.80.0-creating_component_discovery", - "version-0.80.0-creating_component_loading", - "version-0.80.0-creating_component_generic_discovery" - ] - }, - "version-0.80.0-Misc": { - "Introduction": [ - "version-0.80.0-misc" - ], - "External API": [ - "version-0.80.0-external_api_rest", - "version-0.80.0-external_api_rest_python", - "version-0.80.0-external_api_websocket", - "version-0.80.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.80.0-internationalization_index", - "version-0.80.0-internationalization_backend_localization", - "version-0.80.0-internationalization_custom_component_localization", - "version-0.80.0-internationalization_translation" - ], - "Documentation": [ - "version-0.80.0-documentation_index", - "version-0.80.0-documentation_standards", - "version-0.80.0-documentation_create_page" - ], - "Intents": [ - "version-0.80.0-intent_index", - "version-0.80.0-intent_firing", - "version-0.80.0-intent_handling", - "version-0.80.0-intent_conversation", - "version-0.80.0-intent_builtin" - ], - "asyncio": [ - "version-0.80.0-asyncio_index", - "version-0.80.0-asyncio_101", - "version-0.80.0-asyncio_categorizing_functions", - "version-0.80.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.80.0-hassio_debugging", - "version-0.80.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.80.0-hassio_addon_index", - "version-0.80.0-hassio_addon_tutorial", - "version-0.80.0-hassio_addon_config", - "version-0.80.0-hassio_addon_communication", - "version-0.80.0-hassio_addon_testing", - "version-0.80.0-hassio_addon_publishing", - "version-0.80.0-hassio_addon_presentation", - "version-0.80.0-hassio_addon_repository", - "version-0.80.0-hassio_addon_security" - ], - "Maintainer docs": [ - "version-0.80.0-maintenance", - "version-0.80.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.83.0-sidebars.json b/website/versioned_sidebars/version-0.83.0-sidebars.json deleted file mode 100644 index 53d5a44d..00000000 --- a/website/versioned_sidebars/version-0.83.0-sidebars.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "version-0.83.0-Architecture": { - "Architecture": [ - "version-0.83.0-architecture_index", - "version-0.83.0-architecture_components", - "version-0.83.0-architecture_entities", - "version-0.83.0-architecture_hassio" - ], - "Entities": [ - "version-0.83.0-entity_index", - "version-0.83.0-entity_alarm_control_panel", - "version-0.83.0-entity_binary_sensor", - "version-0.83.0-entity_climate", - "version-0.83.0-entity_cover", - "version-0.83.0-entity_fan", - "version-0.83.0-entity_light", - "version-0.83.0-entity_lock", - "version-0.83.0-entity_media_player", - "version-0.83.0-entity_remote", - "version-0.83.0-entity_sensor", - "version-0.83.0-entity_switch", - "version-0.83.0-entity_vacuum", - "version-0.83.0-entity_water_heater", - "version-0.83.0-entity_weather" - ], - "Authentication": [ - "version-0.83.0-auth_index", - "version-0.83.0-auth_permissions", - "version-0.83.0-auth_api", - "version-0.83.0-auth_auth_provider", - "version-0.83.0-auth_auth_module" - ], - "Configuration.yaml": [ - "version-0.83.0-configuration_yaml_index" - ], - "Config Entries": [ - "version-0.83.0-config_entries_index", - "version-0.83.0-config_entries_config_flow_handler" - ], - "Data Entry Flow": [ - "version-0.83.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.83.0-entity_registry_index" - ], - "Device Registry": [ - "version-0.83.0-device_registry_index" - ] - }, - "version-0.83.0-Extending Frontend": { - "Frontend": [ - "version-0.83.0-frontend_index", - "version-0.83.0-frontend_architecture", - "version-0.83.0-frontend_development", - "version-0.83.0-frontend_data", - "version-0.83.0-frontend_external_auth" - ], - "Extending the frontend": [ - "version-0.83.0-frontend_add_card", - "version-0.83.0-frontend_add_more_info", - "version-0.83.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.83.0-lovelace_custom_card", - "version-0.83.0-frontend_creating_custom_ui", - "version-0.83.0-frontend_creating_custom_panels" - ] - }, - "version-0.83.0-Extending HASS": { - "Developing a feature": [ - "version-0.83.0-development_index", - "version-0.83.0-development_environment", - "version-0.83.0-development_submitting", - "version-0.83.0-development_checklist", - "version-0.83.0-development_guidelines", - "version-0.83.0-development_testing", - "version-0.83.0-development_catching_up", - "version-0.83.0-development_validation", - "version-0.83.0-development_typing" - ], - "Development 101": [ - "version-0.83.0-dev_101_index", - "version-0.83.0-dev_101_hass", - "version-0.83.0-dev_101_events", - "version-0.83.0-dev_101_states", - "version-0.83.0-dev_101_services", - "version-0.83.0-dev_101_config" - ], - "Integration Quality Scale": [ - "version-0.83.0-integration_quality_scale_index" - ], - "Creating Platforms": [ - "version-0.83.0-creating_platform_index", - "version-0.83.0-creating_platform_code_review", - "version-0.83.0-creating_platform_example_light", - "version-0.83.0-creating_platform_example_sensor" - ], - "Creating Components": [ - "version-0.83.0-creating_component_index", - "version-0.83.0-creating_component_code_review", - "version-0.83.0-creating_component_deps_and_reqs", - "version-0.83.0-creating_component_events", - "version-0.83.0-creating_component_states", - "version-0.83.0-creating_component_discovery", - "version-0.83.0-creating_component_loading", - "version-0.83.0-creating_component_generic_discovery" - ] - }, - "version-0.83.0-Misc": { - "Introduction": [ - "version-0.83.0-misc" - ], - "External API": [ - "version-0.83.0-external_api_rest", - "version-0.83.0-external_api_rest_python", - "version-0.83.0-external_api_websocket", - "version-0.83.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.83.0-internationalization_index", - "version-0.83.0-internationalization_backend_localization", - "version-0.83.0-internationalization_custom_component_localization", - "version-0.83.0-internationalization_translation" - ], - "Documentation": [ - "version-0.83.0-documentation_index", - "version-0.83.0-documentation_standards", - "version-0.83.0-documentation_create_page" - ], - "Intents": [ - "version-0.83.0-intent_index", - "version-0.83.0-intent_firing", - "version-0.83.0-intent_handling", - "version-0.83.0-intent_conversation", - "version-0.83.0-intent_builtin" - ], - "Native App Integration": [ - "version-0.83.0-app_integration_index", - "version-0.83.0-app_integration_setup", - "version-0.83.0-app_integration_sending_data", - "version-0.83.0-app_integration_webview" - ], - "asyncio": [ - "version-0.83.0-asyncio_index", - "version-0.83.0-asyncio_101", - "version-0.83.0-asyncio_categorizing_functions", - "version-0.83.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.83.0-hassio_debugging", - "version-0.83.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.83.0-hassio_addon_index", - "version-0.83.0-hassio_addon_tutorial", - "version-0.83.0-hassio_addon_config", - "version-0.83.0-hassio_addon_communication", - "version-0.83.0-hassio_addon_testing", - "version-0.83.0-hassio_addon_publishing", - "version-0.83.0-hassio_addon_presentation", - "version-0.83.0-hassio_addon_repository", - "version-0.83.0-hassio_addon_security" - ], - "Maintainer docs": [ - "version-0.83.0-maintenance", - "version-0.83.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.87.0-sidebars.json b/website/versioned_sidebars/version-0.87.0-sidebars.json deleted file mode 100644 index 928b44aa..00000000 --- a/website/versioned_sidebars/version-0.87.0-sidebars.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "version-0.87.0-Architecture": { - "Architecture": [ - "version-0.87.0-architecture_index", - "version-0.87.0-architecture_components", - "version-0.87.0-architecture_entities", - "version-0.87.0-architecture_hassio" - ], - "Entities": [ - "version-0.87.0-entity_index", - "version-0.87.0-entity_air_quality", - "version-0.87.0-entity_alarm_control_panel", - "version-0.87.0-entity_binary_sensor", - "version-0.87.0-entity_climate", - "version-0.87.0-entity_cover", - "version-0.87.0-entity_fan", - "version-0.87.0-entity_light", - "version-0.87.0-entity_lock", - "version-0.87.0-entity_media_player", - "version-0.87.0-entity_remote", - "version-0.87.0-entity_sensor", - "version-0.87.0-entity_switch", - "version-0.87.0-entity_vacuum", - "version-0.87.0-entity_water_heater", - "version-0.87.0-entity_weather" - ], - "Authentication": [ - "version-0.87.0-auth_index", - "version-0.87.0-auth_permissions", - "version-0.87.0-auth_api", - "version-0.87.0-auth_auth_provider", - "version-0.87.0-auth_auth_module" - ], - "Configuration.yaml": [ - "version-0.87.0-configuration_yaml_index" - ], - "Config Entries": [ - "version-0.87.0-config_entries_index", - "version-0.87.0-config_entries_config_flow_handler" - ], - "Data Entry Flow": [ - "version-0.87.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.87.0-entity_registry_index" - ], - "Device Registry": [ - "version-0.87.0-device_registry_index" - ], - "Area Registry": [ - "version-0.87.0-area_registry_index" - ] - }, - "version-0.87.0-Extending Frontend": { - "Frontend": [ - "version-0.87.0-frontend_index", - "version-0.87.0-frontend_architecture", - "version-0.87.0-frontend_development", - "version-0.87.0-frontend_data", - "version-0.87.0-frontend_external_auth" - ], - "Extending the frontend": [ - "version-0.87.0-frontend_add_card", - "version-0.87.0-frontend_add_more_info", - "version-0.87.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.87.0-lovelace_custom_card", - "version-0.87.0-frontend_creating_custom_ui", - "version-0.87.0-frontend_creating_custom_panels" - ] - }, - "version-0.87.0-Extending HASS": { - "Developing a feature": [ - "version-0.87.0-development_index", - "version-0.87.0-development_environment", - "version-0.87.0-development_submitting", - "version-0.87.0-development_checklist", - "version-0.87.0-development_guidelines", - "version-0.87.0-development_testing", - "version-0.87.0-development_catching_up", - "version-0.87.0-development_validation", - "version-0.87.0-development_typing" - ], - "Development 101": [ - "version-0.87.0-dev_101_index", - "version-0.87.0-dev_101_hass", - "version-0.87.0-dev_101_events", - "version-0.87.0-dev_101_states", - "version-0.87.0-dev_101_services", - "version-0.87.0-dev_101_config" - ], - "Integration Quality Scale": [ - "version-0.87.0-integration_quality_scale_index" - ], - "Creating Platforms": [ - "version-0.87.0-creating_platform_index", - "version-0.87.0-creating_platform_code_review", - "version-0.87.0-creating_platform_example_light", - "version-0.87.0-creating_platform_example_sensor" - ], - "Creating Components": [ - "version-0.87.0-creating_component_index", - "version-0.87.0-creating_component_code_review", - "version-0.87.0-creating_component_deps_and_reqs", - "version-0.87.0-creating_component_events", - "version-0.87.0-creating_component_states", - "version-0.87.0-creating_component_discovery", - "version-0.87.0-creating_component_loading", - "version-0.87.0-creating_component_generic_discovery" - ] - }, - "version-0.87.0-Misc": { - "Introduction": [ - "version-0.87.0-misc" - ], - "External API": [ - "version-0.87.0-external_api_rest", - "version-0.87.0-external_api_rest_python", - "version-0.87.0-external_api_websocket", - "version-0.87.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.87.0-internationalization_index", - "version-0.87.0-internationalization_backend_localization", - "version-0.87.0-internationalization_custom_component_localization", - "version-0.87.0-internationalization_translation" - ], - "Documentation": [ - "version-0.87.0-documentation_index", - "version-0.87.0-documentation_standards", - "version-0.87.0-documentation_create_page" - ], - "Intents": [ - "version-0.87.0-intent_index", - "version-0.87.0-intent_firing", - "version-0.87.0-intent_handling", - "version-0.87.0-intent_conversation", - "version-0.87.0-intent_builtin" - ], - "Native App Integration": [ - "version-0.87.0-app_integration_index", - "version-0.87.0-app_integration_setup", - "version-0.87.0-app_integration_sending_data", - "version-0.87.0-app_integration_webview" - ], - "asyncio": [ - "version-0.87.0-asyncio_index", - "version-0.87.0-asyncio_101", - "version-0.87.0-asyncio_categorizing_functions", - "version-0.87.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.87.0-hassio_debugging", - "version-0.87.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.87.0-hassio_addon_index", - "version-0.87.0-hassio_addon_tutorial", - "version-0.87.0-hassio_addon_config", - "version-0.87.0-hassio_addon_communication", - "version-0.87.0-hassio_addon_testing", - "version-0.87.0-hassio_addon_publishing", - "version-0.87.0-hassio_addon_presentation", - "version-0.87.0-hassio_addon_repository", - "version-0.87.0-hassio_addon_security" - ], - "Maintainer docs": [ - "version-0.87.0-maintenance", - "version-0.87.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.89.0-sidebars.json b/website/versioned_sidebars/version-0.89.0-sidebars.json deleted file mode 100644 index 4c6d424a..00000000 --- a/website/versioned_sidebars/version-0.89.0-sidebars.json +++ /dev/null @@ -1,174 +0,0 @@ -{ - "version-0.89.0-Architecture": { - "Architecture": [ - "version-0.89.0-architecture_index", - "version-0.89.0-architecture_components", - "version-0.89.0-architecture_entities", - "version-0.89.0-architecture_hassio" - ], - "Entities": [ - "version-0.89.0-entity_index", - "version-0.89.0-entity_air_quality", - "version-0.89.0-entity_alarm_control_panel", - "version-0.89.0-entity_binary_sensor", - "version-0.89.0-entity_climate", - "version-0.89.0-entity_cover", - "version-0.89.0-entity_fan", - "version-0.89.0-entity_light", - "version-0.89.0-entity_lock", - "version-0.89.0-entity_media_player", - "version-0.89.0-entity_remote", - "version-0.89.0-entity_sensor", - "version-0.89.0-entity_switch", - "version-0.89.0-entity_vacuum", - "version-0.89.0-entity_water_heater", - "version-0.89.0-entity_weather" - ], - "Authentication": [ - "version-0.89.0-auth_index", - "version-0.89.0-auth_permissions", - "version-0.89.0-auth_api", - "version-0.89.0-auth_auth_provider", - "version-0.89.0-auth_auth_module" - ], - "Configuration.yaml": [ - "version-0.89.0-configuration_yaml_index" - ], - "Config Entries": [ - "version-0.89.0-config_entries_index", - "version-0.89.0-config_entries_config_flow_handler", - "version-0.89.0-config_entries_options_flow_handler" - ], - "Data Entry Flow": [ - "version-0.89.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.89.0-entity_registry_index" - ], - "Device Registry": [ - "version-0.89.0-device_registry_index" - ], - "Area Registry": [ - "version-0.89.0-area_registry_index" - ] - }, - "version-0.89.0-Extending Frontend": { - "Frontend": [ - "version-0.89.0-frontend_index", - "version-0.89.0-frontend_architecture", - "version-0.89.0-frontend_development", - "version-0.89.0-frontend_data", - "version-0.89.0-frontend_external_auth" - ], - "Extending the frontend": [ - "version-0.89.0-frontend_add_card", - "version-0.89.0-frontend_add_more_info", - "version-0.89.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.89.0-lovelace_custom_card", - "version-0.89.0-frontend_creating_custom_ui", - "version-0.89.0-frontend_creating_custom_panels" - ] - }, - "version-0.89.0-Extending HASS": { - "Developing a feature": [ - "version-0.89.0-development_index", - "version-0.89.0-development_environment", - "version-0.89.0-development_submitting", - "version-0.89.0-development_checklist", - "version-0.89.0-development_guidelines", - "version-0.89.0-development_testing", - "version-0.89.0-development_catching_up", - "version-0.89.0-development_validation", - "version-0.89.0-development_typing" - ], - "Development 101": [ - "version-0.89.0-dev_101_index", - "version-0.89.0-dev_101_hass", - "version-0.89.0-dev_101_events", - "version-0.89.0-dev_101_states", - "version-0.89.0-dev_101_services", - "version-0.89.0-dev_101_config" - ], - "Integration Quality Scale": [ - "version-0.89.0-integration_quality_scale_index" - ], - "Creating Platforms": [ - "version-0.89.0-creating_platform_index", - "version-0.89.0-creating_platform_code_review", - "version-0.89.0-creating_platform_example_light", - "version-0.89.0-creating_platform_example_sensor" - ], - "Creating Components": [ - "version-0.89.0-creating_component_index", - "version-0.89.0-creating_component_code_review", - "version-0.89.0-creating_component_deps_and_reqs", - "version-0.89.0-creating_component_events", - "version-0.89.0-creating_component_states", - "version-0.89.0-creating_component_discovery", - "version-0.89.0-creating_component_loading", - "version-0.89.0-creating_component_generic_discovery" - ] - }, - "version-0.89.0-Misc": { - "Introduction": [ - "version-0.89.0-misc" - ], - "External API": [ - "version-0.89.0-external_api_rest", - "version-0.89.0-external_api_rest_python", - "version-0.89.0-external_api_websocket", - "version-0.89.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.89.0-internationalization_index", - "version-0.89.0-internationalization_backend_localization", - "version-0.89.0-internationalization_custom_component_localization", - "version-0.89.0-internationalization_translation" - ], - "Documentation": [ - "version-0.89.0-documentation_index", - "version-0.89.0-documentation_standards", - "version-0.89.0-documentation_create_page" - ], - "Intents": [ - "version-0.89.0-intent_index", - "version-0.89.0-intent_firing", - "version-0.89.0-intent_handling", - "version-0.89.0-intent_conversation", - "version-0.89.0-intent_builtin" - ], - "Native App Integration": [ - "version-0.89.0-app_integration_index", - "version-0.89.0-app_integration_setup", - "version-0.89.0-app_integration_sending_data", - "version-0.89.0-app_integration_webview" - ], - "asyncio": [ - "version-0.89.0-asyncio_index", - "version-0.89.0-asyncio_101", - "version-0.89.0-asyncio_categorizing_functions", - "version-0.89.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.89.0-hassio_debugging", - "version-0.89.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.89.0-hassio_addon_index", - "version-0.89.0-hassio_addon_tutorial", - "version-0.89.0-hassio_addon_config", - "version-0.89.0-hassio_addon_communication", - "version-0.89.0-hassio_addon_testing", - "version-0.89.0-hassio_addon_publishing", - "version-0.89.0-hassio_addon_presentation", - "version-0.89.0-hassio_addon_repository", - "version-0.89.0-hassio_addon_security" - ], - "Maintainer docs": [ - "version-0.89.0-maintenance", - "version-0.89.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.91.2-sidebars.json b/website/versioned_sidebars/version-0.91.2-sidebars.json deleted file mode 100644 index e0d6ff90..00000000 --- a/website/versioned_sidebars/version-0.91.2-sidebars.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "version-0.91.2-Architecture": { - "Architecture": [ - "version-0.91.2-architecture_index", - "version-0.91.2-architecture_components", - "version-0.91.2-architecture_entities", - "version-0.91.2-architecture_hassio" - ], - "Entities": [ - "version-0.91.2-entity_index", - "version-0.91.2-entity_air_quality", - "version-0.91.2-entity_alarm_control_panel", - "version-0.91.2-entity_binary_sensor", - "version-0.91.2-entity_climate", - "version-0.91.2-entity_cover", - "version-0.91.2-entity_fan", - "version-0.91.2-entity_light", - "version-0.91.2-entity_lock", - "version-0.91.2-entity_media_player", - "version-0.91.2-entity_remote", - "version-0.91.2-entity_sensor", - "version-0.91.2-entity_switch", - "version-0.91.2-entity_vacuum", - "version-0.91.2-entity_water_heater", - "version-0.91.2-entity_weather" - ], - "Authentication": [ - "version-0.91.2-auth_index", - "version-0.91.2-auth_permissions", - "version-0.91.2-auth_api", - "version-0.91.2-auth_auth_provider", - "version-0.91.2-auth_auth_module" - ], - "Config Entries": [ - "version-0.91.2-config_entries_index" - ], - "Data Entry Flow": [ - "version-0.91.2-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.91.2-entity_registry_index" - ], - "Device Registry": [ - "version-0.91.2-device_registry_index" - ], - "Area Registry": [ - "version-0.91.2-area_registry_index" - ] - }, - "version-0.91.2-Extending Frontend": { - "Frontend": [ - "version-0.91.2-frontend_index", - "version-0.91.2-frontend_architecture", - "version-0.91.2-frontend_development", - "version-0.91.2-frontend_data", - "version-0.91.2-frontend_external_auth" - ], - "Extending the frontend": [ - "version-0.91.2-frontend_add_card", - "version-0.91.2-frontend_add_more_info", - "version-0.91.2-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.91.2-lovelace_custom_card", - "version-0.91.2-frontend_creating_custom_ui", - "version-0.91.2-frontend_creating_custom_panels" - ] - }, - "version-0.91.2-Extending HASS": { - "Development Workflow": [ - "version-0.91.2-development_index", - "version-0.91.2-development_environment", - "version-0.91.2-development_submitting", - "version-0.91.2-development_guidelines", - "version-0.91.2-development_testing", - "version-0.91.2-development_catching_up" - ], - "Building Integrations": [ - "version-0.91.2-creating_integration_file_structure", - "version-0.91.2-creating_integration_manifest", - "version-0.91.2-creating_component_index", - "version-0.91.2-config_entries_config_flow_handler", - "version-0.91.2-config_entries_options_flow_handler", - "version-0.91.2-configuration_yaml_index", - "version-0.91.2-dev_101_services", - "version-0.91.2-creating_platform_index", - "version-0.91.2-creating_component_generic_discovery" - ], - "Development Checklist": [ - "version-0.91.2-development_checklist", - "version-0.91.2-creating_component_code_review", - "version-0.91.2-creating_platform_code_review", - "version-0.91.2-integration_quality_scale_index" - ], - "Home Assistant Core 101": [ - "version-0.91.2-dev_101_index", - "version-0.91.2-dev_101_hass", - "version-0.91.2-dev_101_events", - "version-0.91.2-dev_101_states", - "version-0.91.2-dev_101_config" - ], - "Misc": [ - "version-0.91.2-development_validation", - "version-0.91.2-development_typing" - ] - }, - "version-0.91.2-Misc": { - "Introduction": [ - "version-0.91.2-misc" - ], - "External API": [ - "version-0.91.2-external_api_rest", - "version-0.91.2-external_api_rest_python", - "version-0.91.2-external_api_websocket", - "version-0.91.2-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.91.2-internationalization_index", - "version-0.91.2-internationalization_backend_localization", - "version-0.91.2-internationalization_custom_component_localization", - "version-0.91.2-internationalization_translation" - ], - "Documentation": [ - "version-0.91.2-documentation_index", - "version-0.91.2-documentation_standards", - "version-0.91.2-documentation_create_page" - ], - "Intents": [ - "version-0.91.2-intent_index", - "version-0.91.2-intent_firing", - "version-0.91.2-intent_handling", - "version-0.91.2-intent_conversation", - "version-0.91.2-intent_builtin" - ], - "Native App Integration": [ - "version-0.91.2-app_integration_index", - "version-0.91.2-app_integration_setup", - "version-0.91.2-app_integration_sending_data", - "version-0.91.2-app_integration_sensors", - "version-0.91.2-app_integration_notifications", - "version-0.91.2-app_integration_webview" - ], - "asyncio": [ - "version-0.91.2-asyncio_index", - "version-0.91.2-asyncio_101", - "version-0.91.2-asyncio_categorizing_functions", - "version-0.91.2-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.91.2-hassio_debugging", - "version-0.91.2-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.91.2-hassio_addon_index", - "version-0.91.2-hassio_addon_tutorial", - "version-0.91.2-hassio_addon_config", - "version-0.91.2-hassio_addon_communication", - "version-0.91.2-hassio_addon_testing", - "version-0.91.2-hassio_addon_publishing", - "version-0.91.2-hassio_addon_presentation", - "version-0.91.2-hassio_addon_repository", - "version-0.91.2-hassio_addon_security" - ], - "Maintainer docs": [ - "version-0.91.2-maintenance", - "version-0.91.2-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.94.0-sidebars.json b/website/versioned_sidebars/version-0.94.0-sidebars.json deleted file mode 100644 index cb38f998..00000000 --- a/website/versioned_sidebars/version-0.94.0-sidebars.json +++ /dev/null @@ -1,169 +0,0 @@ -{ - "version-0.94.0-Architecture": { - "Architecture": [ - "version-0.94.0-architecture_index", - "version-0.94.0-architecture_components", - "version-0.94.0-architecture_entities", - "version-0.94.0-architecture_hassio" - ], - "Entities": [ - "version-0.94.0-entity_index", - "version-0.94.0-entity_air_quality", - "version-0.94.0-entity_alarm_control_panel", - "version-0.94.0-entity_binary_sensor", - "version-0.94.0-entity_climate", - "version-0.94.0-entity_cover", - "version-0.94.0-entity_fan", - "version-0.94.0-entity_light", - "version-0.94.0-entity_lock", - "version-0.94.0-entity_media_player", - "version-0.94.0-entity_remote", - "version-0.94.0-entity_sensor", - "version-0.94.0-entity_switch", - "version-0.94.0-entity_vacuum", - "version-0.94.0-entity_water_heater", - "version-0.94.0-entity_weather" - ], - "Authentication": [ - "version-0.94.0-auth_index", - "version-0.94.0-auth_permissions", - "version-0.94.0-auth_api", - "version-0.94.0-auth_auth_provider", - "version-0.94.0-auth_auth_module" - ], - "Config Entries": [ - "version-0.94.0-config_entries_index" - ], - "Data Entry Flow": [ - "version-0.94.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.94.0-entity_registry_index" - ], - "Device Registry": [ - "version-0.94.0-device_registry_index" - ], - "Area Registry": [ - "version-0.94.0-area_registry_index" - ] - }, - "version-0.94.0-Extending Frontend": { - "Frontend": [ - "version-0.94.0-frontend_index", - "version-0.94.0-frontend_architecture", - "version-0.94.0-frontend_development", - "version-0.94.0-frontend_data", - "version-0.94.0-frontend_external_auth", - "version-0.94.0-frontend_external_bus" - ], - "Extending the frontend": [ - "version-0.94.0-frontend_add_card", - "version-0.94.0-frontend_add_more_info", - "version-0.94.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.94.0-lovelace_custom_card", - "version-0.94.0-frontend_creating_custom_panels" - ] - }, - "version-0.94.0-Extending HASS": { - "Development Workflow": [ - "version-0.94.0-development_index", - "version-0.94.0-development_environment", - "version-0.94.0-development_submitting", - "version-0.94.0-development_guidelines", - "version-0.94.0-development_testing", - "version-0.94.0-development_catching_up" - ], - "Building Integrations": [ - "version-0.94.0-creating_integration_file_structure", - "version-0.94.0-creating_integration_manifest", - "version-0.94.0-creating_component_index", - "version-0.94.0-config_entries_config_flow_handler", - "version-0.94.0-config_entries_options_flow_handler", - "version-0.94.0-configuration_yaml_index", - "version-0.94.0-dev_101_services", - "version-0.94.0-creating_platform_index", - "version-0.94.0-creating_component_generic_discovery" - ], - "Development Checklist": [ - "version-0.94.0-development_checklist", - "version-0.94.0-creating_component_code_review", - "version-0.94.0-creating_platform_code_review", - "version-0.94.0-integration_quality_scale_index" - ], - "Home Assistant Core 101": [ - "version-0.94.0-dev_101_index", - "version-0.94.0-dev_101_hass", - "version-0.94.0-dev_101_events", - "version-0.94.0-dev_101_states", - "version-0.94.0-dev_101_config" - ], - "Misc": [ - "version-0.94.0-development_validation", - "version-0.94.0-development_typing" - ] - }, - "version-0.94.0-Misc": { - "Introduction": [ - "version-0.94.0-misc" - ], - "External API": [ - "version-0.94.0-external_api_rest", - "version-0.94.0-external_api_rest_python", - "version-0.94.0-external_api_websocket", - "version-0.94.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.94.0-internationalization_index", - "version-0.94.0-internationalization_backend_localization", - "version-0.94.0-internationalization_custom_component_localization", - "version-0.94.0-internationalization_translation" - ], - "Documentation": [ - "version-0.94.0-documentation_index", - "version-0.94.0-documentation_standards", - "version-0.94.0-documentation_create_page" - ], - "Intents": [ - "version-0.94.0-intent_index", - "version-0.94.0-intent_firing", - "version-0.94.0-intent_handling", - "version-0.94.0-intent_conversation", - "version-0.94.0-intent_builtin" - ], - "Native App Integration": [ - "version-0.94.0-app_integration_index", - "version-0.94.0-app_integration_setup", - "version-0.94.0-app_integration_sending_data", - "version-0.94.0-app_integration_sensors", - "version-0.94.0-app_integration_notifications", - "version-0.94.0-app_integration_webview" - ], - "asyncio": [ - "version-0.94.0-asyncio_index", - "version-0.94.0-asyncio_101", - "version-0.94.0-asyncio_categorizing_functions", - "version-0.94.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.94.0-hassio_debugging", - "version-0.94.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.94.0-hassio_addon_index", - "version-0.94.0-hassio_addon_tutorial", - "version-0.94.0-hassio_addon_config", - "version-0.94.0-hassio_addon_communication", - "version-0.94.0-hassio_addon_testing", - "version-0.94.0-hassio_addon_publishing", - "version-0.94.0-hassio_addon_presentation", - "version-0.94.0-hassio_addon_repository", - "version-0.94.0-hassio_addon_security" - ], - "Maintainer docs": [ - "version-0.94.0-maintenance", - "version-0.94.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.98.0-sidebars.json b/website/versioned_sidebars/version-0.98.0-sidebars.json deleted file mode 100644 index ca8d8286..00000000 --- a/website/versioned_sidebars/version-0.98.0-sidebars.json +++ /dev/null @@ -1,170 +0,0 @@ -{ - "version-0.98.0-Architecture": { - "Architecture": [ - "version-0.98.0-architecture_index", - "version-0.98.0-architecture_components", - "version-0.98.0-architecture_entities", - "version-0.98.0-architecture_hassio" - ], - "Entities": [ - "version-0.98.0-entity_index", - "version-0.98.0-entity_air_quality", - "version-0.98.0-entity_alarm_control_panel", - "version-0.98.0-entity_binary_sensor", - "version-0.98.0-entity_climate", - "version-0.98.0-entity_cover", - "version-0.98.0-entity_fan", - "version-0.98.0-entity_light", - "version-0.98.0-entity_lock", - "version-0.98.0-entity_media_player", - "version-0.98.0-entity_remote", - "version-0.98.0-entity_sensor", - "version-0.98.0-entity_switch", - "version-0.98.0-entity_vacuum", - "version-0.98.0-entity_water_heater", - "version-0.98.0-entity_weather" - ], - "Authentication": [ - "version-0.98.0-auth_index", - "version-0.98.0-auth_permissions", - "version-0.98.0-auth_api", - "version-0.98.0-auth_auth_provider", - "version-0.98.0-auth_auth_module" - ], - "Config Entries": [ - "version-0.98.0-config_entries_index" - ], - "Data Entry Flow": [ - "version-0.98.0-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.98.0-entity_registry_index", - "version-0.98.0-entity_registry_disabled_by" - ], - "Device Registry": [ - "version-0.98.0-device_registry_index" - ], - "Area Registry": [ - "version-0.98.0-area_registry_index" - ] - }, - "version-0.98.0-Extending Frontend": { - "Frontend": [ - "version-0.98.0-frontend_index", - "version-0.98.0-frontend_architecture", - "version-0.98.0-frontend_development", - "version-0.98.0-frontend_data", - "version-0.98.0-frontend_external_auth", - "version-0.98.0-frontend_external_bus" - ], - "Extending the frontend": [ - "version-0.98.0-frontend_add_card", - "version-0.98.0-frontend_add_more_info", - "version-0.98.0-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.98.0-lovelace_custom_card", - "version-0.98.0-frontend_creating_custom_panels" - ] - }, - "version-0.98.0-Extending HASS": { - "Development Workflow": [ - "version-0.98.0-development_index", - "version-0.98.0-development_environment", - "version-0.98.0-development_submitting", - "version-0.98.0-development_guidelines", - "version-0.98.0-development_testing", - "version-0.98.0-development_catching_up" - ], - "Building Integrations": [ - "version-0.98.0-creating_integration_file_structure", - "version-0.98.0-creating_integration_manifest", - "version-0.98.0-creating_component_index", - "version-0.98.0-config_entries_config_flow_handler", - "version-0.98.0-config_entries_options_flow_handler", - "version-0.98.0-configuration_yaml_index", - "version-0.98.0-dev_101_services", - "version-0.98.0-creating_platform_index", - "version-0.98.0-creating_component_generic_discovery" - ], - "Development Checklist": [ - "version-0.98.0-development_checklist", - "version-0.98.0-creating_component_code_review", - "version-0.98.0-creating_platform_code_review", - "version-0.98.0-integration_quality_scale_index" - ], - "Home Assistant Core 101": [ - "version-0.98.0-dev_101_index", - "version-0.98.0-dev_101_hass", - "version-0.98.0-dev_101_events", - "version-0.98.0-dev_101_states", - "version-0.98.0-dev_101_config" - ], - "Misc": [ - "version-0.98.0-development_validation", - "version-0.98.0-development_typing" - ] - }, - "version-0.98.0-Misc": { - "Introduction": [ - "version-0.98.0-misc" - ], - "External API": [ - "version-0.98.0-external_api_rest", - "version-0.98.0-external_api_rest_python", - "version-0.98.0-external_api_websocket", - "version-0.98.0-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.98.0-internationalization_index", - "version-0.98.0-internationalization_backend_localization", - "version-0.98.0-internationalization_custom_component_localization", - "version-0.98.0-internationalization_translation" - ], - "Documentation": [ - "version-0.98.0-documentation_index", - "version-0.98.0-documentation_standards", - "version-0.98.0-documentation_create_page" - ], - "Intents": [ - "version-0.98.0-intent_index", - "version-0.98.0-intent_firing", - "version-0.98.0-intent_handling", - "version-0.98.0-intent_conversation", - "version-0.98.0-intent_builtin" - ], - "Native App Integration": [ - "version-0.98.0-app_integration_index", - "version-0.98.0-app_integration_setup", - "version-0.98.0-app_integration_sending_data", - "version-0.98.0-app_integration_sensors", - "version-0.98.0-app_integration_notifications", - "version-0.98.0-app_integration_webview" - ], - "asyncio": [ - "version-0.98.0-asyncio_index", - "version-0.98.0-asyncio_101", - "version-0.98.0-asyncio_categorizing_functions", - "version-0.98.0-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.98.0-hassio_debugging", - "version-0.98.0-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.98.0-hassio_addon_index", - "version-0.98.0-hassio_addon_tutorial", - "version-0.98.0-hassio_addon_config", - "version-0.98.0-hassio_addon_communication", - "version-0.98.0-hassio_addon_testing", - "version-0.98.0-hassio_addon_publishing", - "version-0.98.0-hassio_addon_presentation", - "version-0.98.0-hassio_addon_repository", - "version-0.98.0-hassio_addon_security" - ], - "Maintainer docs": [ - "version-0.98.0-maintenance", - "version-0.98.0-releasing" - ] - } -} diff --git a/website/versioned_sidebars/version-0.99.3-sidebars.json b/website/versioned_sidebars/version-0.99.3-sidebars.json deleted file mode 100644 index 22c0dac2..00000000 --- a/website/versioned_sidebars/version-0.99.3-sidebars.json +++ /dev/null @@ -1,177 +0,0 @@ -{ - "version-0.99.3-Architecture": { - "Architecture": [ - "version-0.99.3-architecture_index", - "version-0.99.3-architecture_components", - "version-0.99.3-architecture_entities", - "version-0.99.3-architecture_hassio" - ], - "Entities": [ - "version-0.99.3-entity_index", - "version-0.99.3-entity_air_quality", - "version-0.99.3-entity_alarm_control_panel", - "version-0.99.3-entity_binary_sensor", - "version-0.99.3-entity_climate", - "version-0.99.3-entity_cover", - "version-0.99.3-entity_fan", - "version-0.99.3-entity_light", - "version-0.99.3-entity_lock", - "version-0.99.3-entity_media_player", - "version-0.99.3-entity_remote", - "version-0.99.3-entity_sensor", - "version-0.99.3-entity_switch", - "version-0.99.3-entity_vacuum", - "version-0.99.3-entity_water_heater", - "version-0.99.3-entity_weather" - ], - "Authentication": [ - "version-0.99.3-auth_index", - "version-0.99.3-auth_permissions", - "version-0.99.3-auth_api", - "version-0.99.3-auth_auth_provider", - "version-0.99.3-auth_auth_module" - ], - "Config Entries": [ - "version-0.99.3-config_entries_index" - ], - "Data Entry Flow": [ - "version-0.99.3-data_entry_flow_index" - ], - "Entity Registry": [ - "version-0.99.3-entity_registry_index", - "version-0.99.3-entity_registry_disabled_by" - ], - "Device Registry": [ - "version-0.99.3-device_registry_index" - ], - "Area Registry": [ - "version-0.99.3-area_registry_index" - ] - }, - "version-0.99.3-Extending Frontend": { - "Frontend": [ - "version-0.99.3-frontend_index", - "version-0.99.3-frontend_architecture", - "version-0.99.3-frontend_development", - "version-0.99.3-frontend_data", - "version-0.99.3-frontend_external_auth", - "version-0.99.3-frontend_external_bus" - ], - "Extending the frontend": [ - "version-0.99.3-frontend_add_card", - "version-0.99.3-frontend_add_more_info", - "version-0.99.3-frontend_add_websocket_api" - ], - "Custom UI": [ - "version-0.99.3-lovelace_custom_card", - "version-0.99.3-frontend_creating_custom_panels" - ] - }, - "version-0.99.3-Extending HASS": { - "Development Workflow": [ - "version-0.99.3-development_index", - "version-0.99.3-development_environment", - "version-0.99.3-development_submitting", - "version-0.99.3-development_guidelines", - "version-0.99.3-development_testing", - "version-0.99.3-development_catching_up" - ], - "Building Integrations": [ - "version-0.99.3-creating_integration_file_structure", - "version-0.99.3-creating_integration_manifest", - "version-0.99.3-creating_component_index", - "version-0.99.3-config_entries_config_flow_handler", - "version-0.99.3-config_entries_options_flow_handler", - "version-0.99.3-configuration_yaml_index", - "version-0.99.3-dev_101_services", - "version-0.99.3-creating_platform_index", - "version-0.99.3-creating_component_generic_discovery", - "version-0.99.3-reproduce_state_index" - ], - "Development Checklist": [ - "version-0.99.3-development_checklist", - "version-0.99.3-creating_component_code_review", - "version-0.99.3-creating_platform_code_review", - "version-0.99.3-integration_quality_scale_index" - ], - "Home Assistant Core 101": [ - "version-0.99.3-dev_101_index", - "version-0.99.3-dev_101_hass", - "version-0.99.3-dev_101_events", - "version-0.99.3-dev_101_states", - "version-0.99.3-dev_101_config" - ], - "Device Automations": [ - "version-0.99.3-device_automation_index", - "version-0.99.3-device_automation_trigger", - "version-0.99.3-device_automation_condition", - "version-0.99.3-device_automation_action" - ], - "Misc": [ - "version-0.99.3-development_validation", - "version-0.99.3-development_typing" - ] - }, - "version-0.99.3-Misc": { - "Introduction": [ - "version-0.99.3-misc" - ], - "External API": [ - "version-0.99.3-external_api_rest", - "version-0.99.3-external_api_rest_python", - "version-0.99.3-external_api_websocket", - "version-0.99.3-external_api_server_sent_events" - ], - "Internationalization": [ - "version-0.99.3-internationalization_index", - "version-0.99.3-internationalization_backend_localization", - "version-0.99.3-internationalization_custom_component_localization", - "version-0.99.3-internationalization_translation" - ], - "Documentation": [ - "version-0.99.3-documentation_index", - "version-0.99.3-documentation_standards", - "version-0.99.3-documentation_create_page" - ], - "Intents": [ - "version-0.99.3-intent_index", - "version-0.99.3-intent_firing", - "version-0.99.3-intent_handling", - "version-0.99.3-intent_conversation", - "version-0.99.3-intent_builtin" - ], - "Native App Integration": [ - "version-0.99.3-app_integration_index", - "version-0.99.3-app_integration_setup", - "version-0.99.3-app_integration_sending_data", - "version-0.99.3-app_integration_sensors", - "version-0.99.3-app_integration_notifications", - "version-0.99.3-app_integration_webview" - ], - "asyncio": [ - "version-0.99.3-asyncio_index", - "version-0.99.3-asyncio_101", - "version-0.99.3-asyncio_categorizing_functions", - "version-0.99.3-asyncio_working_with_async" - ], - "Hass.io": [ - "version-0.99.3-hassio_debugging", - "version-0.99.3-hassio_hass" - ], - "Hass.io Add-Ons": [ - "version-0.99.3-hassio_addon_index", - "version-0.99.3-hassio_addon_tutorial", - "version-0.99.3-hassio_addon_config", - "version-0.99.3-hassio_addon_communication", - "version-0.99.3-hassio_addon_testing", - "version-0.99.3-hassio_addon_publishing", - "version-0.99.3-hassio_addon_presentation", - "version-0.99.3-hassio_addon_repository", - "version-0.99.3-hassio_addon_security" - ], - "Maintainer docs": [ - "version-0.99.3-maintenance", - "version-0.99.3-releasing" - ] - } -} diff --git a/website/versions.json b/website/versions.json deleted file mode 100644 index e00b5517..00000000 --- a/website/versions.json +++ /dev/null @@ -1,39 +0,0 @@ -[ - "0.105.0", - "0.104.0", - "0.103.0", - "0.102.0", - "0.101.0", - "0.100.0", - "0.99.3", - "0.99.0", - "0.98.0", - "0.97.0", - "0.96.0", - "0.95.0", - "0.94.0", - "0.93.0", - "0.92.1", - "0.92.0", - "0.91.2", - "0.91.0", - "0.90.0", - "0.89.0", - "0.88.0", - "0.87.0", - "0.86.0", - "0.85", - "0.84.0", - "0.83.0", - "0.82.0", - "0.81.0", - "0.80.0", - "0.79.0", - "0.78.0", - "0.77.0", - "0.76.0", - "0.75.0", - "0.74.0", - "0.73.0", - "0.72" -] diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 00000000..fa69a2f0 --- /dev/null +++ b/yarn.lock @@ -0,0 +1,9405 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@babel/code-frame@7.5.5": + version "7.5.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.5.5.tgz#bc0782f6d69f7b7d49531219699b988f669a8f9d" + integrity sha512-27d4lZoomVyo51VegxI20xZPuSHusqbQag/ztrBC7wegWoQ1nLREPVSKSW8byhTlzTKyNE4ifaTA6lCp7JjpFw== + dependencies: + "@babel/highlight" "^7.0.0" + +"@babel/code-frame@^7.8.0", "@babel/code-frame@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" + integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== + dependencies: + "@babel/highlight" "^7.8.3" + +"@babel/compat-data@^7.8.4": + version "7.8.5" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.8.5.tgz#d28ce872778c23551cbb9432fc68d28495b613b9" + integrity sha512-jWYUqQX/ObOhG1UiEkbH5SANsE/8oKXiQWjj7p7xgj9Zmnt//aUvyz4dBkK0HNsS8/cbyC5NmmH87VekW+mXFg== + dependencies: + browserslist "^4.8.5" + invariant "^2.2.4" + semver "^5.5.0" + +"@babel/core@7.8.0": + version "7.8.0" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.0.tgz#fd273d4faf69cc20ee3ccfd32d42df916bb4a15c" + integrity sha512-3rqPi/bv/Xfu2YzHvBz4XqMI1fKVwnhntPA1/fjoECrSjrhbOCxlTrbVu5gUtr8zkxW+RpkDOa/HCW93gzS2Dw== + dependencies: + "@babel/code-frame" "^7.8.0" + "@babel/generator" "^7.8.0" + "@babel/helpers" "^7.8.0" + "@babel/parser" "^7.8.0" + "@babel/template" "^7.8.0" + "@babel/traverse" "^7.8.0" + "@babel/types" "^7.8.0" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.0" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/core@^7.7.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.8.4.tgz#d496799e5c12195b3602d0fddd77294e3e38e80e" + integrity sha512-0LiLrB2PwrVI+a2/IEskBopDYSd8BCb3rOvH7D5tzoWd696TBEduBvuLVm4Nx6rltrLZqvI3MCalB2K2aVzQjA== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.4" + "@babel/helpers" "^7.8.4" + "@babel/parser" "^7.8.4" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.4" + "@babel/types" "^7.8.3" + convert-source-map "^1.7.0" + debug "^4.1.0" + gensync "^1.0.0-beta.1" + json5 "^2.1.0" + lodash "^4.17.13" + resolve "^1.3.2" + semver "^5.4.1" + source-map "^0.5.0" + +"@babel/generator@^7.8.0", "@babel/generator@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.8.4.tgz#35bbc74486956fe4251829f9f6c48330e8d0985e" + integrity sha512-PwhclGdRpNAf3IxZb0YVuITPZmmrXz9zf6fH8lT4XbrmfQKr6ryBzhv593P5C6poJRciFCL/eHGW2NuGrgEyxA== + dependencies: + "@babel/types" "^7.8.3" + jsesc "^2.5.1" + lodash "^4.17.13" + source-map "^0.5.0" + +"@babel/helper-annotate-as-pure@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.8.3.tgz#60bc0bc657f63a0924ff9a4b4a0b24a13cf4deee" + integrity sha512-6o+mJrZBxOoEX77Ezv9zwW7WV8DdluouRKNY/IR5u/YTMuKHgugHOzYWlYvYLpLA9nPsQCAAASpCIbjI9Mv+Uw== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-builder-binary-assignment-operator-visitor@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.8.3.tgz#c84097a427a061ac56a1c30ebf54b7b22d241503" + integrity sha512-5eFOm2SyFPK4Rh3XMMRDjN7lBH0orh3ss0g3rTYZnBQ+r6YPj7lgDyCvPphynHvUrobJmeMignBr6Acw9mAPlw== + dependencies: + "@babel/helper-explode-assignable-expression" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-builder-react-jsx@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-builder-react-jsx/-/helper-builder-react-jsx-7.8.3.tgz#dee98d7d79cc1f003d80b76fe01c7f8945665ff6" + integrity sha512-JT8mfnpTkKNCboTqZsQTdGo3l3Ik3l7QIt9hh0O9DYiwVel37VoJpILKM4YFbP2euF32nkQSb+F9cUk9b7DDXQ== + dependencies: + "@babel/types" "^7.8.3" + esutils "^2.0.0" + +"@babel/helper-call-delegate@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-call-delegate/-/helper-call-delegate-7.8.3.tgz#de82619898aa605d409c42be6ffb8d7204579692" + integrity sha512-6Q05px0Eb+N4/GTyKPPvnkig7Lylw+QzihMpws9iiZQv7ZImf84ZsZpQH7QoWN4n4tm81SnSzPgHw2qtO0Zf3A== + dependencies: + "@babel/helper-hoist-variables" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-compilation-targets@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.8.4.tgz#03d7ecd454b7ebe19a254f76617e61770aed2c88" + integrity sha512-3k3BsKMvPp5bjxgMdrFyq0UaEO48HciVrOVF0+lon8pp95cyJ2ujAh0TrBHNMnJGT2rr0iKOJPFFbSqjDyf/Pg== + dependencies: + "@babel/compat-data" "^7.8.4" + browserslist "^4.8.5" + invariant "^2.2.4" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/helper-create-regexp-features-plugin@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.8.3.tgz#c774268c95ec07ee92476a3862b75cc2839beb79" + integrity sha512-Gcsm1OHCUr9o9TcJln57xhWHtdXbA2pgQ58S0Lxlks0WMGNXuki4+GLfX0p+L2ZkINUGZvfkz8rzoqJQSthI+Q== + dependencies: + "@babel/helper-regex" "^7.8.3" + regexpu-core "^4.6.0" + +"@babel/helper-define-map@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-define-map/-/helper-define-map-7.8.3.tgz#a0655cad5451c3760b726eba875f1cd8faa02c15" + integrity sha512-PoeBYtxoZGtct3md6xZOCWPcKuMuk3IHhgxsRRNtnNShebf4C8YonTSblsK4tvDbm+eJAw2HAPOfCr+Q/YRG/g== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/types" "^7.8.3" + lodash "^4.17.13" + +"@babel/helper-explode-assignable-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.8.3.tgz#a728dc5b4e89e30fc2dfc7d04fa28a930653f982" + integrity sha512-N+8eW86/Kj147bO9G2uclsg5pwfs/fqqY5rwgIL7eTBklgXjcOJ3btzS5iM6AitJcftnY7pm2lGsrJVYLGjzIw== + dependencies: + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.8.3.tgz#eeeb665a01b1f11068e9fb86ad56a1cb1a824cca" + integrity sha512-BCxgX1BC2hD/oBlIFUgOCQDOPV8nSINxCwM3o93xP4P9Fq6aV5sgv2cOOITDMtCfQ+3PvHp3l689XZvAM9QyOA== + dependencies: + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-get-function-arity@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-get-function-arity/-/helper-get-function-arity-7.8.3.tgz#b894b947bd004381ce63ea1db9f08547e920abd5" + integrity sha512-FVDR+Gd9iLjUMY1fzE2SR0IuaJToR4RkCDARVfsBBPSP53GEqSFjD8gNyxg246VUyc/ALRxFaAK8rVG7UT7xRA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-hoist-variables@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.8.3.tgz#1dbe9b6b55d78c9b4183fc8cdc6e30ceb83b7134" + integrity sha512-ky1JLOjcDUtSc+xkt0xhYff7Z6ILTAHKmZLHPxAhOP0Nd77O+3nCsd6uSVYur6nJnCI029CrNbYlc0LoPfAPQg== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-member-expression-to-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.8.3.tgz#659b710498ea6c1d9907e0c73f206eee7dadc24c" + integrity sha512-fO4Egq88utkQFjbPrSHGmGLFqmrshs11d46WI+WZDESt7Wu7wN2G2Iu+NMMZJFDOVRHAMIkB5SNh30NtwCA7RA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-module-imports@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.8.3.tgz#7fe39589b39c016331b6b8c3f441e8f0b1419498" + integrity sha512-R0Bx3jippsbAEtzkpZ/6FIiuzOURPcMjHp+Z6xPe6DtApDJx+w7UYyOLanZqO8+wKR9G10s/FmHXvxaMd9s6Kg== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-module-transforms@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.8.3.tgz#d305e35d02bee720fbc2c3c3623aa0c316c01590" + integrity sha512-C7NG6B7vfBa/pwCOshpMbOYUmrYQDfCpVL/JCRu0ek8B5p8kue1+BCXpg2vOYs7w5ACB9GTOBYQ5U6NwrMg+3Q== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + lodash "^4.17.13" + +"@babel/helper-optimise-call-expression@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.8.3.tgz#7ed071813d09c75298ef4f208956006b6111ecb9" + integrity sha512-Kag20n86cbO2AvHca6EJsvqAd82gc6VMGule4HwebwMlwkpXuVqrNRj6CkCV2sKxgi9MyAUnZVnZ6lJ1/vKhHQ== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-plugin-utils@7.8.0": + version "7.8.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.0.tgz#59ec882d43c21c544ccb51decaecb306b34a8231" + integrity sha512-+hAlRGdf8fHQAyNnDBqTHQhwdLURLdrCROoWaEQYiQhk2sV9Rhs+GoFZZfMJExTq9HG8o2NX3uN2G90bFtmFdA== + +"@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.8.3.tgz#9ea293be19babc0f52ff8ca88b34c3611b208670" + integrity sha512-j+fq49Xds2smCUNYmEHF9kGNkhbet6yVIBp4e6oeQpH1RUs/Ir06xUKzDjDkGcaaokPiTNs2JBWHjaE4csUkZQ== + +"@babel/helper-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-regex/-/helper-regex-7.8.3.tgz#139772607d51b93f23effe72105b319d2a4c6965" + integrity sha512-BWt0QtYv/cg/NecOAZMdcn/waj/5P26DR4mVLXfFtDokSR6fyuG0Pj+e2FqtSME+MqED1khnSMulkmGl8qWiUQ== + dependencies: + lodash "^4.17.13" + +"@babel/helper-remap-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.8.3.tgz#273c600d8b9bf5006142c1e35887d555c12edd86" + integrity sha512-kgwDmw4fCg7AVgS4DukQR/roGp+jP+XluJE5hsRZwxCYGg+Rv9wSGErDWhlI90FODdYfd4xG4AQRiMDjjN0GzA== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-wrap-function" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-replace-supers@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.8.3.tgz#91192d25f6abbcd41da8a989d4492574fb1530bc" + integrity sha512-xOUssL6ho41U81etpLoT2RTdvdus4VfHamCuAm4AHxGr+0it5fnwoVdwUJ7GFEqCsQYzJUhcbsN9wB9apcYKFA== + dependencies: + "@babel/helper-member-expression-to-functions" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-simple-access@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-simple-access/-/helper-simple-access-7.8.3.tgz#7f8109928b4dab4654076986af575231deb639ae" + integrity sha512-VNGUDjx5cCWg4vvCTR8qQ7YJYZ+HBjxOgXEl7ounz+4Sn7+LMD3CFrCTEU6/qXKbA2nKg21CwhhBzO0RpRbdCw== + dependencies: + "@babel/template" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helper-split-export-declaration@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.8.3.tgz#31a9f30070f91368a7182cf05f831781065fc7a9" + integrity sha512-3x3yOeyBhW851hroze7ElzdkeRXQYQbFIb7gLK1WQYsw2GWDay5gAJNw1sWJ0VFP6z5J1whqeXH/WCdCjZv6dA== + dependencies: + "@babel/types" "^7.8.3" + +"@babel/helper-wrap-function@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/helper-wrap-function/-/helper-wrap-function-7.8.3.tgz#9dbdb2bb55ef14aaa01fe8c99b629bd5352d8610" + integrity sha512-LACJrbUET9cQDzb6kG7EeD7+7doC3JNvUgTEQOx2qaO1fKlzE/Bf05qs9w1oXQMmXlPO65lC3Tq9S6gZpTErEQ== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/helpers@^7.8.0", "@babel/helpers@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.8.4.tgz#754eb3ee727c165e0a240d6c207de7c455f36f73" + integrity sha512-VPbe7wcQ4chu4TDQjimHv/5tj73qz88o12EPkO2ValS2QiQS/1F2SsjyIGNnAD0vF/nZS6Cf9i+vW6HIlnaR8w== + dependencies: + "@babel/template" "^7.8.3" + "@babel/traverse" "^7.8.4" + "@babel/types" "^7.8.3" + +"@babel/highlight@^7.0.0", "@babel/highlight@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.8.3.tgz#28f173d04223eaaa59bc1d439a3836e6d1265797" + integrity sha512-PX4y5xQUvy0fnEVHrYOarRPXVWafSjTW9T0Hab8gVIawpl2Sj0ORyrygANq+KjcNlSSTw0YCLSNA8OyZ1I4yEg== + dependencies: + chalk "^2.0.0" + esutils "^2.0.2" + js-tokens "^4.0.0" + +"@babel/parser@^7.7.4", "@babel/parser@^7.8.0", "@babel/parser@^7.8.3", "@babel/parser@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.8.4.tgz#d1dbe64691d60358a974295fa53da074dd2ce8e8" + integrity sha512-0fKu/QqildpXmPVaRBoXOlyBb3MC+J0A66x97qEfLOMkn3u6nfY5esWogQwi/K0BjASYy4DbnsEWnpNL6qT5Mw== + +"@babel/plugin-proposal-async-generator-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.8.3.tgz#bad329c670b382589721b27540c7d288601c6e6f" + integrity sha512-NZ9zLv848JsV3hs8ryEh7Uaz/0KsmPLqv0+PdkDJL1cJy0K4kOCFa8zc1E3mp+RHPQcpdfb/6GovEsW4VDrOMw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + +"@babel/plugin-proposal-dynamic-import@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.8.3.tgz#38c4fe555744826e97e2ae930b0fb4cc07e66054" + integrity sha512-NyaBbyLFXFLT9FP+zk0kYlUlA8XtCUbehs67F0nnEg7KICgMc2mNkIeu9TYhKzyXMkrapZFwAhXLdnt4IYHy1w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + +"@babel/plugin-proposal-json-strings@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.8.3.tgz#da5216b238a98b58a1e05d6852104b10f9a70d6b" + integrity sha512-KGhQNZ3TVCQG/MjRbAUwuH+14y9q0tpxs1nWWs3pbSleRdDro9SAMMDyye8HhY1gqZ7/NqIc8SKhya0wRDgP1Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-json-strings" "^7.8.0" + +"@babel/plugin-proposal-nullish-coalescing-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.8.3.tgz#e4572253fdeed65cddeecfdab3f928afeb2fd5d2" + integrity sha512-TS9MlfzXpXKt6YYomudb/KU7nQI6/xnapG6in1uZxoxDghuSMZsPb6D2fyUwNYSAp4l1iR7QtFOjkqcRYcUsfw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + +"@babel/plugin-proposal-object-rest-spread@7.8.0": + version "7.8.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.0.tgz#ca8ac673d32db774c2154a4c7517fd46ec45e9cf" + integrity sha512-SjJ2ZXCylpWC+5DTES0/pbpNmw/FnjU/3dF068xF0DU9aN+oOKah+3MCSFcb4pnZ9IwmxfOy4KnbGJSQR+hAZA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + +"@babel/plugin-proposal-object-rest-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.8.3.tgz#eb5ae366118ddca67bed583b53d7554cad9951bb" + integrity sha512-8qvuPwU/xxUCt78HocNlv0mXXo0wdh9VT1R04WU8HGOfaOob26pF+9P5/lYjN/q7DHOX1bvX60hnhOvuQUJdbA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + +"@babel/plugin-proposal-optional-catch-binding@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.8.3.tgz#9dee96ab1650eed88646ae9734ca167ac4a9c5c9" + integrity sha512-0gkX7J7E+AtAw9fcwlVQj8peP61qhdg/89D5swOkjYbkboA2CVckn3kiyum1DE0wskGb7KJJxBdyEBApDLLVdw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + +"@babel/plugin-proposal-optional-chaining@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.8.3.tgz#ae10b3214cb25f7adb1f3bc87ba42ca10b7e2543" + integrity sha512-QIoIR9abkVn+seDE3OjA08jWcs3eZ9+wJCKSRgo3WdEU2csFYgdScb+8qHB3+WXsGJD55u+5hWCISI7ejXS+kg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + +"@babel/plugin-proposal-unicode-property-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.8.3.tgz#b646c3adea5f98800c9ab45105ac34d06cd4a47f" + integrity sha512-1/1/rEZv2XGweRwwSkLpY+s60za9OZ1hJs4YDqFHCw0kYWYwL5IFljVY1MYBL+weT1l9pokDO2uhSTLVxzoHkQ== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-async-generators@^7.8.0": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz#a983fb1aeb2ec3f6ed042a210f640e90e786fe0d" + integrity sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-dynamic-import@^7.7.4", "@babel/plugin-syntax-dynamic-import@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3" + integrity sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-json-strings@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz#01ca21b668cd8218c9e640cb6dd88c5412b2c96a" + integrity sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@7.8.0": + version "7.8.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.0.tgz#657a0306e2c74de84e0dcf8b6cb024ed990224fc" + integrity sha512-zLDUckAuKeOtxJhfNE0TlR7iEApb2u7EYRlh5cxKzq6A5VzUbYEdyJGJlug41jDbjRbHTtsLKZUnUcy/8V3xZw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-jsx@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.8.3.tgz#521b06c83c40480f1e58b4fd33b92eceb1d6ea94" + integrity sha512-WxdW9xyLgBdefoo0Ynn3MRSkhe5tFVxxKNVdnZSh318WrG2e2jH+E9wd/++JsqcLJZPfz87njQJ8j2Upjm0M0A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-syntax-nullish-coalescing-operator@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz#167ed70368886081f74b5c36c65a88c03b66d1a9" + integrity sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-object-rest-spread@7.8.0": + version "7.8.0" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.0.tgz#9b37d580d459682364d8602494c69145b394fd4c" + integrity sha512-dt89fDlkfkTrQcy5KavMQPyF2A6tR0kYp8HAnIoQv5hO34iAUffHghP/hMGd7Gf/+uYTmLQO0ar7peX1SUWyIA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-object-rest-spread@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz#60e225edcbd98a640332a2e72dd3e66f1af55871" + integrity sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-catch-binding@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz#6111a265bcfb020eb9efd0fdfd7d26402b9ed6c1" + integrity sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-optional-chaining@^7.8.0": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz#4f69c2ab95167e0180cd5336613f8c5788f7d48a" + integrity sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.0" + +"@babel/plugin-syntax-top-level-await@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.8.3.tgz#3acdece695e6b13aaf57fc291d1a800950c71391" + integrity sha512-kwj1j9lL/6Wd0hROD3b/OZZ7MSrZLqqn9RAZ5+cYYsflQ9HZBIKCUkr3+uL1MEJ1NePiUbf98jjiMQSv0NMR9g== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-arrow-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.8.3.tgz#82776c2ed0cd9e1a49956daeb896024c9473b8b6" + integrity sha512-0MRF+KC8EqH4dbuITCWwPSzsyO3HIWWlm30v8BbbpOrS1B++isGxPnnuq/IZvOX5J2D/p7DQalQm+/2PnlKGxg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-async-to-generator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.8.3.tgz#4308fad0d9409d71eafb9b1a6ee35f9d64b64086" + integrity sha512-imt9tFLD9ogt56Dd5CI/6XgpukMwd/fLGSrix2httihVe7LOGVPhyhMh1BU5kDM7iHD08i8uUtmV2sWaBFlHVQ== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-remap-async-to-generator" "^7.8.3" + +"@babel/plugin-transform-block-scoped-functions@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.8.3.tgz#437eec5b799b5852072084b3ae5ef66e8349e8a3" + integrity sha512-vo4F2OewqjbB1+yaJ7k2EJFHlTP3jR634Z9Cj9itpqNjuLXvhlVxgnjsHsdRgASR8xYDrx6onw4vW5H6We0Jmg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-block-scoping@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.8.3.tgz#97d35dab66857a437c166358b91d09050c868f3a" + integrity sha512-pGnYfm7RNRgYRi7bids5bHluENHqJhrV4bCZRwc5GamaWIIs07N4rZECcmJL6ZClwjDz1GbdMZFtPs27hTB06w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + lodash "^4.17.13" + +"@babel/plugin-transform-classes@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.8.3.tgz#46fd7a9d2bb9ea89ce88720477979fe0d71b21b8" + integrity sha512-SjT0cwFJ+7Rbr1vQsvphAHwUHvSUPmMjMU/0P59G8U2HLFqSa082JO7zkbDNWs9kH/IUqpHI6xWNesGf8haF1w== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-define-map" "^7.8.3" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-optimise-call-expression" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + globals "^11.1.0" + +"@babel/plugin-transform-computed-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.8.3.tgz#96d0d28b7f7ce4eb5b120bb2e0e943343c86f81b" + integrity sha512-O5hiIpSyOGdrQZRQ2ccwtTVkgUDBBiCuK//4RJ6UfePllUTCENOzKxfh6ulckXKc0DixTFLCfb2HVkNA7aDpzA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-destructuring@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.8.3.tgz#20ddfbd9e4676906b1056ee60af88590cc7aaa0b" + integrity sha512-H4X646nCkiEcHZUZaRkhE2XVsoz0J/1x3VVujnn96pSoGCtKPA99ZZA+va+gK+92Zycd6OBKCD8tDb/731bhgQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-dotall-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.8.3.tgz#c3c6ec5ee6125c6993c5cbca20dc8621a9ea7a6e" + integrity sha512-kLs1j9Nn4MQoBYdRXH6AeaXMbEJFaFu/v1nQkvib6QzTj8MZI5OQzqmD83/2jEM1z0DLilra5aWO5YpyC0ALIw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-duplicate-keys@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.8.3.tgz#8d12df309aa537f272899c565ea1768e286e21f1" + integrity sha512-s8dHiBUbcbSgipS4SMFuWGqCvyge5V2ZeAWzR6INTVC3Ltjig/Vw1G2Gztv0vU/hRG9X8IvKvYdoksnUfgXOEQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-exponentiation-operator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.8.3.tgz#581a6d7f56970e06bf51560cd64f5e947b70d7b7" + integrity sha512-zwIpuIymb3ACcInbksHaNcR12S++0MDLKkiqXHl3AzpgdKlFNhog+z/K0+TGW+b0w5pgTq4H6IwV/WhxbGYSjQ== + dependencies: + "@babel/helper-builder-binary-assignment-operator-visitor" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-for-of@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.8.4.tgz#6fe8eae5d6875086ee185dd0b098a8513783b47d" + integrity sha512-iAXNlOWvcYUYoV8YIxwS7TxGRJcxyl8eQCfT+A5j8sKUzRFvJdcyjp97jL2IghWSRDaL2PU2O2tX8Cu9dTBq5A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-function-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.8.3.tgz#279373cb27322aaad67c2683e776dfc47196ed8b" + integrity sha512-rO/OnDS78Eifbjn5Py9v8y0aR+aSYhDhqAwVfsTl0ERuMZyr05L1aFSCJnbv2mmsLkit/4ReeQ9N2BgLnOcPCQ== + dependencies: + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.8.3.tgz#aef239823d91994ec7b68e55193525d76dbd5dc1" + integrity sha512-3Tqf8JJ/qB7TeldGl+TT55+uQei9JfYaregDcEAyBZ7akutriFrt6C/wLYIer6OYhleVQvH/ntEhjE/xMmy10A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-member-expression-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.8.3.tgz#963fed4b620ac7cbf6029c755424029fa3a40410" + integrity sha512-3Wk2EXhnw+rP+IDkK6BdtPKsUE5IeZ6QOGrPYvw52NwBStw9V1ZVzxgK6fSKSxqUvH9eQPR3tm3cOq79HlsKYA== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-modules-amd@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.8.3.tgz#65606d44616b50225e76f5578f33c568a0b876a5" + integrity sha512-MadJiU3rLKclzT5kBH4yxdry96odTUwuqrZM+GllFI/VhxfPz+k9MshJM+MwhfkCdxxclSbSBbUGciBngR+kEQ== + dependencies: + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-commonjs@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.8.3.tgz#df251706ec331bd058a34bdd72613915f82928a5" + integrity sha512-JpdMEfA15HZ/1gNuB9XEDlZM1h/gF/YOH7zaZzQu2xCFRfwc01NXBMHHSTT6hRjlXJJs5x/bfODM3LiCk94Sxg== + dependencies: + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-simple-access" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-systemjs@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.8.3.tgz#d8bbf222c1dbe3661f440f2f00c16e9bb7d0d420" + integrity sha512-8cESMCJjmArMYqa9AO5YuMEkE4ds28tMpZcGZB/jl3n0ZzlsxOAi3mC+SKypTfT8gjMupCnd3YiXCkMjj2jfOg== + dependencies: + "@babel/helper-hoist-variables" "^7.8.3" + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + babel-plugin-dynamic-import-node "^2.3.0" + +"@babel/plugin-transform-modules-umd@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.8.3.tgz#592d578ce06c52f5b98b02f913d653ffe972661a" + integrity sha512-evhTyWhbwbI3/U6dZAnx/ePoV7H6OUG+OjiJFHmhr9FPn0VShjwC2kdxqIuQ/+1P50TMrneGzMeyMTFOjKSnAw== + dependencies: + "@babel/helper-module-transforms" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-named-capturing-groups-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.8.3.tgz#a2a72bffa202ac0e2d0506afd0939c5ecbc48c6c" + integrity sha512-f+tF/8UVPU86TrCb06JoPWIdDpTNSGGcAtaD9mLP0aYGA0OS0j7j7DHJR0GTFrUZPUU6loZhbsVZgTh0N+Qdnw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + +"@babel/plugin-transform-new-target@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.8.3.tgz#60cc2ae66d85c95ab540eb34babb6434d4c70c43" + integrity sha512-QuSGysibQpyxexRyui2vca+Cmbljo8bcRckgzYV4kRIsHpVeyeC3JDO63pY+xFZ6bWOBn7pfKZTqV4o/ix9sFw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-object-super@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.8.3.tgz#ebb6a1e7a86ffa96858bd6ac0102d65944261725" + integrity sha512-57FXk+gItG/GejofIyLIgBKTas4+pEU47IXKDBWFTxdPd7F80H8zybyAY7UoblVfBhBGs2EKM+bJUu2+iUYPDQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-replace-supers" "^7.8.3" + +"@babel/plugin-transform-parameters@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.8.4.tgz#1d5155de0b65db0ccf9971165745d3bb990d77d3" + integrity sha512-IsS3oTxeTsZlE5KqzTbcC2sV0P9pXdec53SU+Yxv7o/6dvGM5AkTotQKhoSffhNgZ/dftsSiOoxy7evCYJXzVA== + dependencies: + "@babel/helper-call-delegate" "^7.8.3" + "@babel/helper-get-function-arity" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-property-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.8.3.tgz#33194300d8539c1ed28c62ad5087ba3807b98263" + integrity sha512-uGiiXAZMqEoQhRWMK17VospMZh5sXWg+dlh2soffpkAl96KAm+WZuJfa6lcELotSRmooLqg0MWdH6UUq85nmmg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-react-display-name@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.8.3.tgz#70ded987c91609f78353dd76d2fb2a0bb991e8e5" + integrity sha512-3Jy/PCw8Fe6uBKtEgz3M82ljt+lTg+xJaM4og+eyu83qLT87ZUSckn0wy7r31jflURWLO83TW6Ylf7lyXj3m5A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-react-jsx-self@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.8.3.tgz#c4f178b2aa588ecfa8d077ea80d4194ee77ed702" + integrity sha512-01OT7s5oa0XTLf2I8XGsL8+KqV9lx3EZV+jxn/L2LQ97CGKila2YMroTkCEIE0HV/FF7CMSRsIAybopdN9NTdg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + +"@babel/plugin-transform-react-jsx-source@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.8.3.tgz#951e75a8af47f9f120db731be095d2b2c34920e0" + integrity sha512-PLMgdMGuVDtRS/SzjNEQYUT8f4z1xb2BAT54vM1X5efkVuYBf5WyGUMbpmARcfq3NaglIwz08UVQK4HHHbC6ag== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + +"@babel/plugin-transform-react-jsx@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.8.3.tgz#4220349c0390fdefa505365f68c103562ab2fc4a" + integrity sha512-r0h+mUiyL595ikykci+fbwm9YzmuOrUBi0b+FDIKmi3fPQyFokWVEMJnRWHJPPQEjyFJyna9WZC6Viv6UHSv1g== + dependencies: + "@babel/helper-builder-react-jsx" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-syntax-jsx" "^7.8.3" + +"@babel/plugin-transform-regenerator@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.8.3.tgz#b31031e8059c07495bf23614c97f3d9698bc6ec8" + integrity sha512-qt/kcur/FxrQrzFR432FGZznkVAjiyFtCOANjkAKwCbt465L6ZCiUQh2oMYGU3Wo8LRFJxNDFwWn106S5wVUNA== + dependencies: + regenerator-transform "^0.14.0" + +"@babel/plugin-transform-reserved-words@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.8.3.tgz#9a0635ac4e665d29b162837dd3cc50745dfdf1f5" + integrity sha512-mwMxcycN3omKFDjDQUl+8zyMsBfjRFr0Zn/64I41pmjv4NJuqcYlEtezwYtw9TFd9WR1vN5kiM+O0gMZzO6L0A== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-runtime@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.8.3.tgz#c0153bc0a5375ebc1f1591cb7eea223adea9f169" + integrity sha512-/vqUt5Yh+cgPZXXjmaG9NT8aVfThKk7G4OqkVhrXqwsC5soMn/qTCxs36rZ2QFhpfTJcjw4SNDIZ4RUb8OL4jQ== + dependencies: + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + resolve "^1.8.1" + semver "^5.5.1" + +"@babel/plugin-transform-shorthand-properties@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.8.3.tgz#28545216e023a832d4d3a1185ed492bcfeac08c8" + integrity sha512-I9DI6Odg0JJwxCHzbzW08ggMdCezoWcuQRz3ptdudgwaHxTjxw5HgdFJmZIkIMlRymL6YiZcped4TTCB0JcC8w== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-spread@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.8.3.tgz#9c8ffe8170fdfb88b114ecb920b82fb6e95fe5e8" + integrity sha512-CkuTU9mbmAoFOI1tklFWYYbzX5qCIZVXPVy0jpXgGwkplCndQAa58s2jr66fTeQnA64bDox0HL4U56CFYoyC7g== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-sticky-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.8.3.tgz#be7a1290f81dae767475452199e1f76d6175b100" + integrity sha512-9Spq0vGCD5Bb4Z/ZXXSK5wbbLFMG085qd2vhL1JYu1WcQ5bXqZBAYRzU1d+p79GcHs2szYv5pVQCX13QgldaWw== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/helper-regex" "^7.8.3" + +"@babel/plugin-transform-template-literals@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.8.3.tgz#7bfa4732b455ea6a43130adc0ba767ec0e402a80" + integrity sha512-820QBtykIQOLFT8NZOcTRJ1UNuztIELe4p9DCgvj4NK+PwluSJ49we7s9FB1HIGNIYT7wFUJ0ar2QpCDj0escQ== + dependencies: + "@babel/helper-annotate-as-pure" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-typeof-symbol@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.8.4.tgz#ede4062315ce0aaf8a657a920858f1a2f35fc412" + integrity sha512-2QKyfjGdvuNfHsb7qnBBlKclbD4CfshH2KvDabiijLMGXPHJXGxtDzwIF7bQP+T0ysw8fYTtxPafgfs/c1Lrqg== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/plugin-transform-unicode-regex@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.8.3.tgz#0cef36e3ba73e5c57273effb182f46b91a1ecaad" + integrity sha512-+ufgJjYdmWfSQ+6NS9VGUR2ns8cjJjYbrbi11mZBTaWm+Fui/ncTLFF28Ei1okavY+xkojGr1eJxNsWYeA5aZw== + dependencies: + "@babel/helper-create-regexp-features-plugin" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + +"@babel/preset-env@^7.7.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.8.4.tgz#9dac6df5f423015d3d49b6e9e5fa3413e4a72c4e" + integrity sha512-HihCgpr45AnSOHRbS5cWNTINs0TwaR8BS8xIIH+QwiW8cKL0llV91njQMpeMReEPVs+1Ao0x3RLEBLtt1hOq4w== + dependencies: + "@babel/compat-data" "^7.8.4" + "@babel/helper-compilation-targets" "^7.8.4" + "@babel/helper-module-imports" "^7.8.3" + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-proposal-async-generator-functions" "^7.8.3" + "@babel/plugin-proposal-dynamic-import" "^7.8.3" + "@babel/plugin-proposal-json-strings" "^7.8.3" + "@babel/plugin-proposal-nullish-coalescing-operator" "^7.8.3" + "@babel/plugin-proposal-object-rest-spread" "^7.8.3" + "@babel/plugin-proposal-optional-catch-binding" "^7.8.3" + "@babel/plugin-proposal-optional-chaining" "^7.8.3" + "@babel/plugin-proposal-unicode-property-regex" "^7.8.3" + "@babel/plugin-syntax-async-generators" "^7.8.0" + "@babel/plugin-syntax-dynamic-import" "^7.8.0" + "@babel/plugin-syntax-json-strings" "^7.8.0" + "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.0" + "@babel/plugin-syntax-object-rest-spread" "^7.8.0" + "@babel/plugin-syntax-optional-catch-binding" "^7.8.0" + "@babel/plugin-syntax-optional-chaining" "^7.8.0" + "@babel/plugin-syntax-top-level-await" "^7.8.3" + "@babel/plugin-transform-arrow-functions" "^7.8.3" + "@babel/plugin-transform-async-to-generator" "^7.8.3" + "@babel/plugin-transform-block-scoped-functions" "^7.8.3" + "@babel/plugin-transform-block-scoping" "^7.8.3" + "@babel/plugin-transform-classes" "^7.8.3" + "@babel/plugin-transform-computed-properties" "^7.8.3" + "@babel/plugin-transform-destructuring" "^7.8.3" + "@babel/plugin-transform-dotall-regex" "^7.8.3" + "@babel/plugin-transform-duplicate-keys" "^7.8.3" + "@babel/plugin-transform-exponentiation-operator" "^7.8.3" + "@babel/plugin-transform-for-of" "^7.8.4" + "@babel/plugin-transform-function-name" "^7.8.3" + "@babel/plugin-transform-literals" "^7.8.3" + "@babel/plugin-transform-member-expression-literals" "^7.8.3" + "@babel/plugin-transform-modules-amd" "^7.8.3" + "@babel/plugin-transform-modules-commonjs" "^7.8.3" + "@babel/plugin-transform-modules-systemjs" "^7.8.3" + "@babel/plugin-transform-modules-umd" "^7.8.3" + "@babel/plugin-transform-named-capturing-groups-regex" "^7.8.3" + "@babel/plugin-transform-new-target" "^7.8.3" + "@babel/plugin-transform-object-super" "^7.8.3" + "@babel/plugin-transform-parameters" "^7.8.4" + "@babel/plugin-transform-property-literals" "^7.8.3" + "@babel/plugin-transform-regenerator" "^7.8.3" + "@babel/plugin-transform-reserved-words" "^7.8.3" + "@babel/plugin-transform-shorthand-properties" "^7.8.3" + "@babel/plugin-transform-spread" "^7.8.3" + "@babel/plugin-transform-sticky-regex" "^7.8.3" + "@babel/plugin-transform-template-literals" "^7.8.3" + "@babel/plugin-transform-typeof-symbol" "^7.8.4" + "@babel/plugin-transform-unicode-regex" "^7.8.3" + "@babel/types" "^7.8.3" + browserslist "^4.8.5" + core-js-compat "^3.6.2" + invariant "^2.2.2" + levenary "^1.1.1" + semver "^5.5.0" + +"@babel/preset-react@^7.7.4": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.8.3.tgz#23dc63f1b5b0751283e04252e78cf1d6589273d2" + integrity sha512-9hx0CwZg92jGb7iHYQVgi0tOEHP/kM60CtWJQnmbATSPIQQ2xYzfoCI3EdqAhFBeeJwYMdWQuDUHMsuDbH9hyQ== + dependencies: + "@babel/helper-plugin-utils" "^7.8.3" + "@babel/plugin-transform-react-display-name" "^7.8.3" + "@babel/plugin-transform-react-jsx" "^7.8.3" + "@babel/plugin-transform-react-jsx-self" "^7.8.3" + "@babel/plugin-transform-react-jsx-source" "^7.8.3" + +"@babel/runtime@^7.1.2", "@babel/runtime@^7.4.0", "@babel/runtime@^7.7.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.8.4.tgz#d79f5a2040f7caa24d53e563aad49cbc05581308" + integrity sha512-neAp3zt80trRVBI1x0azq6c57aNBqYZH8KhMm3TaB7wEI5Q4A2SHfBHE8w9gOhI/lrqxtEbXZgQIrHP+wvSGwQ== + dependencies: + regenerator-runtime "^0.13.2" + +"@babel/template@^7.8.0", "@babel/template@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.8.3.tgz#e02ad04fe262a657809327f578056ca15fd4d1b8" + integrity sha512-04m87AcQgAFdvuoyiQ2kgELr2tV8B4fP/xJAVUL3Yb3bkNdMedD3d0rlSQr3PegP0cms3eHjl1F7PWlvWbU8FQ== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/parser" "^7.8.3" + "@babel/types" "^7.8.3" + +"@babel/traverse@^7.7.4", "@babel/traverse@^7.8.0", "@babel/traverse@^7.8.3", "@babel/traverse@^7.8.4": + version "7.8.4" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.8.4.tgz#f0845822365f9d5b0e312ed3959d3f827f869e3c" + integrity sha512-NGLJPZwnVEyBPLI+bl9y9aSnxMhsKz42so7ApAv9D+b4vAFPpY013FTS9LdKxcABoIYFU52HcYga1pPlx454mg== + dependencies: + "@babel/code-frame" "^7.8.3" + "@babel/generator" "^7.8.4" + "@babel/helper-function-name" "^7.8.3" + "@babel/helper-split-export-declaration" "^7.8.3" + "@babel/parser" "^7.8.4" + "@babel/types" "^7.8.3" + debug "^4.1.0" + globals "^11.1.0" + lodash "^4.17.13" + +"@babel/types@^7.8.0", "@babel/types@^7.8.3": + version "7.8.3" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.8.3.tgz#5a383dffa5416db1b73dedffd311ffd0788fb31c" + integrity sha512-jBD+G8+LWpMBBWvVcdr4QysjUE4mU/syrhN17o1u3gx0/WzJB1kwiVZAXRtWbsIPOwW8pF/YJV5+nmetPzepXg== + dependencies: + esutils "^2.0.2" + lodash "^4.17.13" + to-fast-properties "^2.0.0" + +"@csstools/convert-colors@^1.4.0": + version "1.4.0" + resolved "https://registry.yarnpkg.com/@csstools/convert-colors/-/convert-colors-1.4.0.tgz#ad495dc41b12e75d588c6db8b9834f08fa131eb7" + integrity sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw== + +"@docusaurus/core@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/core/-/core-2.0.0-alpha.40.tgz#cefc79156b89316317aee289fc68547b1d0ced04" + integrity sha512-3mVw7vXm6Ad53+1qKvYD3EzULC/JyWH8dUlysLzbsWx3M6+ZJ4NNdNTtLM4Uuug8OdnbhIJL244O4wSeRT5U3Q== + dependencies: + "@babel/core" "^7.7.4" + "@babel/plugin-syntax-dynamic-import" "^7.7.4" + "@babel/plugin-transform-runtime" "^7.7.4" + "@babel/preset-env" "^7.7.4" + "@babel/preset-react" "^7.7.4" + "@babel/runtime" "^7.7.4" + "@docusaurus/utils" "^2.0.0-alpha.40" + "@endiliey/static-site-generator-webpack-plugin" "^4.0.0" + babel-loader "^8.0.6" + babel-plugin-dynamic-import-node "^2.3.0" + cache-loader "^4.1.0" + chalk "^3.0.0" + chokidar "^3.3.0" + classnames "^2.2.6" + commander "^4.0.1" + copy-webpack-plugin "^5.0.5" + core-js "^2.6.5" + css-loader "^3.2.0" + del "^5.1.0" + ejs "^3.0.1" + express "^4.17.1" + fs-extra "^8.1.0" + globby "^10.0.1" + html-minifier-terser "^5.0.2" + html-tags "^3.1.0" + html-webpack-plugin "^4.0.0-beta.11" + import-fresh "^3.2.1" + lodash "^4.17.15" + mini-css-extract-plugin "^0.8.0" + nprogress "^0.2.0" + null-loader "^3.0.0" + optimize-css-assets-webpack-plugin "^5.0.3" + portfinder "^1.0.25" + postcss-loader "^3.0.0" + postcss-preset-env "^6.7.0" + react-dev-utils "^9.1.0" + react-helmet "^6.0.0-beta" + react-loadable "^5.5.0" + react-loadable-ssr-addon "^0.2.0" + react-router "^5.1.2" + react-router-config "^5.1.1" + react-router-dom "^5.1.2" + semver "^6.3.0" + shelljs "^0.8.3" + std-env "^2.2.1" + terser-webpack-plugin "^2.2.1" + wait-file "^1.0.5" + webpack "^4.41.2" + webpack-bundle-analyzer "^3.6.0" + webpack-dev-server "^3.9.0" + webpack-merge "^4.2.2" + webpackbar "^4.0.0" + +"@docusaurus/mdx-loader@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/mdx-loader/-/mdx-loader-2.0.0-alpha.40.tgz#26670dd07ff4b91831257f9b375400fe05a10e0c" + integrity sha512-v63OQKDf2DxN5SG9brKC2h5xDY9I8e0CGs/uNMF6txpVA/XYTNc2yP+XXUZS3Vx9xVIPH8uLruTZr5/bx2XH7w== + dependencies: + "@babel/parser" "^7.7.4" + "@babel/traverse" "^7.7.4" + "@mdx-js/mdx" "^1.5.1" + "@mdx-js/react" "^1.5.1" + escape-html "^1.0.3" + fs-extra "^8.1.0" + github-slugger "^1.2.1" + gray-matter "^4.0.2" + loader-utils "^1.2.3" + mdast-util-to-string "^1.0.7" + remark-emoji "^2.0.2" + remark-slug "^5.1.2" + stringify-object "^3.3.0" + unist-util-visit "^2.0.1" + +"@docusaurus/plugin-content-blog@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.0.0-alpha.40.tgz#e586f2af7e4736094eb4af5d2cc305877e4ef80a" + integrity sha512-iLCWtkQNe08+kYWlZC52WE3b3LDoYqh7mQYr2sOPmuZYmUv6wm88I7QMP3FlEpSIsYrIVy6yRoOGpD7Lf43wlA== + dependencies: + "@docusaurus/mdx-loader" "^2.0.0-alpha.40" + "@docusaurus/utils" "^2.0.0-alpha.40" + feed "^4.0.0" + fs-extra "^8.1.0" + globby "^10.0.1" + loader-utils "^1.2.3" + lodash "^4.17.15" + +"@docusaurus/plugin-content-docs@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.0.0-alpha.40.tgz#acec3e8b7c9deba415131fb8b53b618c039b06b5" + integrity sha512-cZgGJGNtYXlR2CQI7EuPyzf7DV1RvX+gRSRcPn979XxuLyk2GRWJ1/ODS3jkjQOfTat1QMFYvFrF5vYAgN6Drg== + dependencies: + "@docusaurus/mdx-loader" "^2.0.0-alpha.40" + "@docusaurus/utils" "^2.0.0-alpha.40" + execa "^3.4.0" + fs-extra "^8.1.0" + globby "^10.0.1" + import-fresh "^3.2.1" + loader-utils "^1.2.3" + lodash "^4.17.15" + shelljs "^0.8.3" + +"@docusaurus/plugin-content-pages@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.0.0-alpha.40.tgz#2edc4f906d9e30d4adac834d1a5ac8fab54b703e" + integrity sha512-igSyxGgzuJASLJ5969hyYx2x5B2jNDPu28BEiDbWP3sx1hwVZ+p+kXB8BlY1zlQob/NCGRH2LAR2Cyyb6o3Ntg== + dependencies: + "@docusaurus/types" "^2.0.0-alpha.40" + "@docusaurus/utils" "^2.0.0-alpha.40" + globby "^10.0.1" + +"@docusaurus/plugin-google-analytics@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.0.0-alpha.40.tgz#1967ff433c1dfc3d0cf29e17bc078232f2344119" + integrity sha512-vWkx63QadZgxTi2J+nLRnAd4uuCJT/F1rhRB8wVoUR/Vkeo463oufNWQL5yDpC1FA2d54zAwaLbjSbTSyuD4TA== + +"@docusaurus/plugin-google-gtag@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.0.0-alpha.40.tgz#9f6e372c39175615a70f53cdd4d4bb91fbbb07ac" + integrity sha512-2cBdCAsgLGg2uqSFf85GfUxsuqlmBIpmJhQrA/4Bc+ECc9mPxVq4UdD3C8YafUbiUzgNB2GTRv1igMBM4d7hEQ== + +"@docusaurus/plugin-sitemap@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.0.0-alpha.40.tgz#32c9fdff8fee20fbebb18f15fd49a2b01a2560b5" + integrity sha512-Z7VoC1o8+9gsy8LCiqgkYJmWKqzpIKjfydD5AX0D46vWMohfCnDIvWPKS4uN7BcCm9HRL786tJu3v3821N8I0A== + dependencies: + "@docusaurus/types" "^2.0.0-alpha.40" + sitemap "^3.2.2" + +"@docusaurus/preset-classic@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/preset-classic/-/preset-classic-2.0.0-alpha.40.tgz#7b45eb699c8512a3601c9dd2707b1c283edd8d6a" + integrity sha512-CALOb3aB1WR9JbK6ogMosy4ReZnkvtfCOJy49ibQqdVcJnmI46CbBscjHgbNph87tY9U/uzRb32XlP7mcScmng== + dependencies: + "@docusaurus/plugin-content-blog" "^2.0.0-alpha.40" + "@docusaurus/plugin-content-docs" "^2.0.0-alpha.40" + "@docusaurus/plugin-content-pages" "^2.0.0-alpha.40" + "@docusaurus/plugin-google-analytics" "^2.0.0-alpha.40" + "@docusaurus/plugin-google-gtag" "^2.0.0-alpha.40" + "@docusaurus/plugin-sitemap" "^2.0.0-alpha.40" + "@docusaurus/theme-classic" "^2.0.0-alpha.40" + "@docusaurus/theme-search-algolia" "^2.0.0-alpha.40" + +"@docusaurus/theme-classic@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-classic/-/theme-classic-2.0.0-alpha.40.tgz#e6b6ee684d9499a895d2df894b4772db9d299939" + integrity sha512-kksNoAD4AD/klNJAuMWIWvkTP3aV85iozoNeihLALbTGQejEWxCbRL+dBjUflhF9zrKcvZP3s905hKj7Xt3B3g== + dependencies: + "@mdx-js/mdx" "^1.5.1" + "@mdx-js/react" "^1.5.1" + classnames "^2.2.6" + clipboard "^2.0.4" + infima "0.2.0-alpha.3" + parse-numeric-range "^0.0.2" + prism-react-renderer "^1.0.2" + react-toggle "^4.1.1" + +"@docusaurus/theme-search-algolia@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.0.0-alpha.40.tgz#f3f133d8ff392cfee5d5e1f7c102f6800bf54516" + integrity sha512-dCCu7JN5/WmJv6bBTpgbCuvz6LlQr6/pRMsWsShQPxal7JpgMAyVjLCdqL9byY+mJONQrWbpxPTWEHl9nZ9Mdw== + dependencies: + classnames "^2.2.6" + docsearch.js "^2.6.3" + +"@docusaurus/types@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/types/-/types-2.0.0-alpha.40.tgz#be0af577dd6f4ef3202620f7e21acc7843a56bee" + integrity sha512-CcEVeONauYMaqECauAwt9p9ux4r8C7ww+ipaSLxG9wwzeYVgoVPWnIDlKSBIyx2UBWzGz4er+V6eGpHLY15x8Q== + dependencies: + "@types/webpack" "^4.41.0" + commander "^4.0.1" + querystring "0.2.0" + +"@docusaurus/utils@^2.0.0-alpha.40": + version "2.0.0-alpha.40" + resolved "https://registry.yarnpkg.com/@docusaurus/utils/-/utils-2.0.0-alpha.40.tgz#fbbde31886ea1076a8d14e2133f07a6d35cf158e" + integrity sha512-MR1nD3o23PuyWuSX0n+bGXlGfWt08w1xrVDRb+J4M3LrOflSlgI2RaT2p3J7V/czNWcvfCjhknVNXqpVTViw6A== + dependencies: + escape-string-regexp "^2.0.0" + fs-extra "^8.1.0" + gray-matter "^4.0.2" + lodash "^4.17.15" + +"@endiliey/static-site-generator-webpack-plugin@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@endiliey/static-site-generator-webpack-plugin/-/static-site-generator-webpack-plugin-4.0.0.tgz#94bfe58fd83aeda355de797fcb5112adaca3a6b1" + integrity sha512-3MBqYCs30qk1OBRC697NqhGouYbs71D1B8hrk/AFJC6GwF2QaJOQZtA1JYAaGSe650sZ8r5ppRTtCRXepDWlng== + dependencies: + bluebird "^3.7.1" + cheerio "^0.22.0" + eval "^0.1.4" + url "^0.11.0" + webpack-sources "^1.4.3" + +"@hapi/address@2.x.x": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@hapi/address/-/address-2.1.4.tgz#5d67ed43f3fd41a69d4b9ff7b56e7c0d1d0a81e5" + integrity sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ== + +"@hapi/bourne@1.x.x": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@hapi/bourne/-/bourne-1.3.2.tgz#0a7095adea067243ce3283e1b56b8a8f453b242a" + integrity sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA== + +"@hapi/hoek@8.x.x", "@hapi/hoek@^8.3.0": + version "8.5.1" + resolved "https://registry.yarnpkg.com/@hapi/hoek/-/hoek-8.5.1.tgz#fde96064ca446dec8c55a8c2f130957b070c6e06" + integrity sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow== + +"@hapi/joi@^15.1.0": + version "15.1.1" + resolved "https://registry.yarnpkg.com/@hapi/joi/-/joi-15.1.1.tgz#c675b8a71296f02833f8d6d243b34c57b8ce19d7" + integrity sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ== + dependencies: + "@hapi/address" "2.x.x" + "@hapi/bourne" "1.x.x" + "@hapi/hoek" "8.x.x" + "@hapi/topo" "3.x.x" + +"@hapi/topo@3.x.x": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@hapi/topo/-/topo-3.1.6.tgz#68d935fa3eae7fdd5ab0d7f953f3205d8b2bfc29" + integrity sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ== + dependencies: + "@hapi/hoek" "^8.3.0" + +"@mdx-js/mdx@^1.5.1": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@mdx-js/mdx/-/mdx-1.5.5.tgz#09dc8932af84e5baf5add2625ad0250a117c3363" + integrity sha512-Xv1lJ+VWt8giWQrqf4GdIBxl08SfepfIWAnuuIzuR+wA59SaXDvkW6XFIvl8u495OQEB1eugMvq8l2XR8ZGr1A== + dependencies: + "@babel/core" "7.8.0" + "@babel/plugin-syntax-jsx" "7.8.0" + "@babel/plugin-syntax-object-rest-spread" "7.8.0" + "@mdx-js/util" "^1.5.5" + babel-plugin-apply-mdx-type-prop "^1.5.5" + babel-plugin-extract-import-names "^1.5.5" + camelcase-css "2.0.1" + detab "2.0.2" + hast-util-raw "5.0.1" + lodash.uniq "4.5.0" + mdast-util-to-hast "6.0.2" + remark-mdx "^1.5.5" + remark-parse "7.0.2" + remark-squeeze-paragraphs "3.0.4" + style-to-object "0.3.0" + unified "8.4.2" + unist-builder "1.0.4" + unist-util-visit "2.0.1" + +"@mdx-js/react@^1.5.1": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@mdx-js/react/-/react-1.5.5.tgz#0036e65ec59521059f33292f535b9ef0d67bd0e6" + integrity sha512-Qwvri4zyU9ZbhhXsH0wfSZ/J9b8mARRTB6GSCTnyKRffO2CaQXl9oLsvRAeQSLRei/onEARc+RexH+jMeNS1rw== + +"@mdx-js/util@^1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@mdx-js/util/-/util-1.5.5.tgz#6f88bcb847ebd0117fc81bcd26b83220062fd881" + integrity sha512-IudQkyZuM8T1CrSX9r0ShPXCABjtEtyrV4lxQqhKAwFqw1aYpy/5LOZhitMLoJTybZPVdPotuh+zjqYy9ZOSbA== + +"@mrmlnc/readdir-enhanced@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz#524af240d1a360527b730475ecfa1344aa540dde" + integrity sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g== + dependencies: + call-me-maybe "^1.0.1" + glob-to-regexp "^0.3.0" + +"@nodelib/fs.scandir@2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.3.tgz#3a582bdb53804c6ba6d146579c46e52130cf4a3b" + integrity sha512-eGmwYQn3gxo4r7jdQnkrrN6bY478C3P+a/y72IJukF8LjB6ZHeB3c+Ehacj3sYeSmUXGlnA67/PmbM9CVwL7Dw== + dependencies: + "@nodelib/fs.stat" "2.0.3" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.3", "@nodelib/fs.stat@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.3.tgz#34dc5f4cabbc720f4e60f75a747e7ecd6c175bd3" + integrity sha512-bQBFruR2TAwoevBEd/NWMoAAtNGzTRgdrqnYCc7dhzfoNvqPzLyqlEQnzZ3kVnNrSp25iyxE00/3h2fqGAGArA== + +"@nodelib/fs.stat@^1.1.2": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" + integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.4" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.4.tgz#011b9202a70a6366e436ca5c065844528ab04976" + integrity sha512-1V9XOY4rDW0rehzbrcqAmHnz8e7SKvX27gh8Gt2WgB0+pdzdiLV83p72kZPU+jvMbS1qU5mauP2iOvO8rhmurQ== + dependencies: + "@nodelib/fs.scandir" "2.1.3" + fastq "^1.6.0" + +"@types/anymatch@*": + version "1.3.1" + resolved "https://registry.yarnpkg.com/@types/anymatch/-/anymatch-1.3.1.tgz#336badc1beecb9dacc38bea2cf32adf627a8421a" + integrity sha512-/+CRPXpBDpo2RK9C68N3b2cOvO0Cf5B9aPijHsoDQTHivnGSObdOF2BRQOYjojWTDy6nQvMjmqRXIxH55VjxxA== + +"@types/color-name@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@types/color-name/-/color-name-1.1.1.tgz#1c1261bbeaa10a8055bbc5d8ab84b7b2afc846a0" + integrity sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ== + +"@types/events@*": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/events/-/events-3.0.0.tgz#2862f3f58a9a7f7c3e78d79f130dd4d71c25c2a7" + integrity sha512-EaObqwIvayI5a8dCzhFrjKzVwKLxjoG9T6Ppd5CEo07LRKfQ8Yokw54r5+Wq7FaBQ+yXRvQAYPrHwya1/UFt9g== + +"@types/glob@^7.1.1": + version "7.1.1" + resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.1.tgz#aa59a1c6e3fbc421e07ccd31a944c30eba521575" + integrity sha512-1Bh06cbWJUHMC97acuD6UMG29nMt0Aqz1vF3guLfG+kHHJhy3AyohZFFxYk2f7Q1SQIrNwvncxAE0N/9s70F2w== + dependencies: + "@types/events" "*" + "@types/minimatch" "*" + "@types/node" "*" + +"@types/minimatch@*": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@types/minimatch/-/minimatch-3.0.3.tgz#3dca0e3f33b200fc7d1139c0cd96c1268cadfd9d" + integrity sha512-tHq6qdbT9U1IRSGf14CL0pUlULksvY9OZ+5eEgl1N7t+OA3tGvNpxJCzuKQlsNgCVwbAs670L1vcVQi8j9HjnA== + +"@types/node@*": + version "13.7.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-13.7.1.tgz#238eb34a66431b71d2aaddeaa7db166f25971a0d" + integrity sha512-Zq8gcQGmn4txQEJeiXo/KiLpon8TzAl0kmKH4zdWctPj05nWwp1ClMdAVEloqrQKfaC48PNLdgN/aVaLqUrluA== + +"@types/q@^1.5.1": + version "1.5.2" + resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.2.tgz#690a1475b84f2a884fd07cd797c00f5f31356ea8" + integrity sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw== + +"@types/source-list-map@*": + version "0.1.2" + resolved "https://registry.yarnpkg.com/@types/source-list-map/-/source-list-map-0.1.2.tgz#0078836063ffaf17412349bba364087e0ac02ec9" + integrity sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA== + +"@types/tapable@*": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.5.tgz#9adbc12950582aa65ead76bffdf39fe0c27a3c02" + integrity sha512-/gG2M/Imw7cQFp8PGvz/SwocNrmKFjFsm5Pb8HdbHkZ1K8pmuPzOX4VeVoiEecFCVf4CsN1r3/BRvx+6sNqwtQ== + +"@types/uglify-js@*": + version "3.0.4" + resolved "https://registry.yarnpkg.com/@types/uglify-js/-/uglify-js-3.0.4.tgz#96beae23df6f561862a830b4288a49e86baac082" + integrity sha512-SudIN9TRJ+v8g5pTG8RRCqfqTMNqgWCKKd3vtynhGzkIIjxaicNAMuY5TRadJ6tzDu3Dotf3ngaMILtmOdmWEQ== + dependencies: + source-map "^0.6.1" + +"@types/unist@^2.0.0", "@types/unist@^2.0.2": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.3.tgz#9c088679876f374eb5983f150d4787aa6fb32d7e" + integrity sha512-FvUupuM3rlRsRtCN+fDudtmytGO6iHJuuRKS1Ss0pG5z8oX0diNEw94UEL7hgDbpN94rgaK5R7sWm6RrSkZuAQ== + +"@types/webpack-sources@*": + version "0.1.6" + resolved "https://registry.yarnpkg.com/@types/webpack-sources/-/webpack-sources-0.1.6.tgz#3d21dfc2ec0ad0c77758e79362426a9ba7d7cbcb" + integrity sha512-FtAWR7wR5ocJ9+nP137DV81tveD/ZgB1sadnJ/axUGM3BUVfRPx8oQNMtv3JNfTeHx3VP7cXiyfR/jmtEsVHsQ== + dependencies: + "@types/node" "*" + "@types/source-list-map" "*" + source-map "^0.6.1" + +"@types/webpack@^4.41.0": + version "4.41.6" + resolved "https://registry.yarnpkg.com/@types/webpack/-/webpack-4.41.6.tgz#c76afbdef59159d12e3e1332dc264b75574722a2" + integrity sha512-iWRpV5Ej+8uKrgxp6jXz3v7ZTjgtuMXY+rsxQjFNU0hYCnHkpA7vtiNffgxjuxX4feFHBbz0IF76OzX2OqDYPw== + dependencies: + "@types/anymatch" "*" + "@types/node" "*" + "@types/tapable" "*" + "@types/uglify-js" "*" + "@types/webpack-sources" "*" + source-map "^0.6.0" + +"@webassemblyjs/ast@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.8.5.tgz#51b1c5fe6576a34953bf4b253df9f0d490d9e359" + integrity sha512-aJMfngIZ65+t71C3y2nBBg5FFG0Okt9m0XEgWZ7Ywgn1oMAT8cNwx00Uv1cQyHtidq0Xn94R4TAywO+LCQ+ZAQ== + dependencies: + "@webassemblyjs/helper-module-context" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/wast-parser" "1.8.5" + +"@webassemblyjs/floating-point-hex-parser@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.8.5.tgz#1ba926a2923613edce496fd5b02e8ce8a5f49721" + integrity sha512-9p+79WHru1oqBh9ewP9zW95E3XAo+90oth7S5Re3eQnECGq59ly1Ri5tsIipKGpiStHsUYmY3zMLqtk3gTcOtQ== + +"@webassemblyjs/helper-api-error@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.8.5.tgz#c49dad22f645227c5edb610bdb9697f1aab721f7" + integrity sha512-Za/tnzsvnqdaSPOUXHyKJ2XI7PDX64kWtURyGiJJZKVEdFOsdKUCPTNEVFZq3zJ2R0G5wc2PZ5gvdTRFgm81zA== + +"@webassemblyjs/helper-buffer@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.8.5.tgz#fea93e429863dd5e4338555f42292385a653f204" + integrity sha512-Ri2R8nOS0U6G49Q86goFIPNgjyl6+oE1abW1pS84BuhP1Qcr5JqMwRFT3Ah3ADDDYGEgGs1iyb1DGX+kAi/c/Q== + +"@webassemblyjs/helper-code-frame@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.8.5.tgz#9a740ff48e3faa3022b1dff54423df9aa293c25e" + integrity sha512-VQAadSubZIhNpH46IR3yWO4kZZjMxN1opDrzePLdVKAZ+DFjkGD/rf4v1jap744uPVU6yjL/smZbRIIJTOUnKQ== + dependencies: + "@webassemblyjs/wast-printer" "1.8.5" + +"@webassemblyjs/helper-fsm@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-fsm/-/helper-fsm-1.8.5.tgz#ba0b7d3b3f7e4733da6059c9332275d860702452" + integrity sha512-kRuX/saORcg8se/ft6Q2UbRpZwP4y7YrWsLXPbbmtepKr22i8Z4O3V5QE9DbZK908dh5Xya4Un57SDIKwB9eow== + +"@webassemblyjs/helper-module-context@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-module-context/-/helper-module-context-1.8.5.tgz#def4b9927b0101dc8cbbd8d1edb5b7b9c82eb245" + integrity sha512-/O1B236mN7UNEU4t9X7Pj38i4VoU8CcMHyy3l2cV/kIF4U5KoHXDVqcDuOs1ltkac90IM4vZdHc52t1x8Yfs3g== + dependencies: + "@webassemblyjs/ast" "1.8.5" + mamacro "^0.0.3" + +"@webassemblyjs/helper-wasm-bytecode@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.8.5.tgz#537a750eddf5c1e932f3744206551c91c1b93e61" + integrity sha512-Cu4YMYG3Ddl72CbmpjU/wbP6SACcOPVbHN1dI4VJNJVgFwaKf1ppeFJrwydOG3NDHxVGuCfPlLZNyEdIYlQ6QQ== + +"@webassemblyjs/helper-wasm-section@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.8.5.tgz#74ca6a6bcbe19e50a3b6b462847e69503e6bfcbf" + integrity sha512-VV083zwR+VTrIWWtgIUpqfvVdK4ff38loRmrdDBgBT8ADXYsEZ5mPQ4Nde90N3UYatHdYoDIFb7oHzMncI02tA== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-buffer" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/wasm-gen" "1.8.5" + +"@webassemblyjs/ieee754@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.8.5.tgz#712329dbef240f36bf57bd2f7b8fb9bf4154421e" + integrity sha512-aaCvQYrvKbY/n6wKHb/ylAJr27GglahUO89CcGXMItrOBqRarUMxWLJgxm9PJNuKULwN5n1csT9bYoMeZOGF3g== + dependencies: + "@xtuc/ieee754" "^1.2.0" + +"@webassemblyjs/leb128@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.8.5.tgz#044edeb34ea679f3e04cd4fd9824d5e35767ae10" + integrity sha512-plYUuUwleLIziknvlP8VpTgO4kqNaH57Y3JnNa6DLpu/sGcP6hbVdfdX5aHAV716pQBKrfuU26BJK29qY37J7A== + dependencies: + "@xtuc/long" "4.2.2" + +"@webassemblyjs/utf8@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.8.5.tgz#a8bf3b5d8ffe986c7c1e373ccbdc2a0915f0cedc" + integrity sha512-U7zgftmQriw37tfD934UNInokz6yTmn29inT2cAetAsaU9YeVCveWEwhKL1Mg4yS7q//NGdzy79nlXh3bT8Kjw== + +"@webassemblyjs/wasm-edit@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.8.5.tgz#962da12aa5acc1c131c81c4232991c82ce56e01a" + integrity sha512-A41EMy8MWw5yvqj7MQzkDjU29K7UJq1VrX2vWLzfpRHt3ISftOXqrtojn7nlPsZ9Ijhp5NwuODuycSvfAO/26Q== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-buffer" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/helper-wasm-section" "1.8.5" + "@webassemblyjs/wasm-gen" "1.8.5" + "@webassemblyjs/wasm-opt" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + "@webassemblyjs/wast-printer" "1.8.5" + +"@webassemblyjs/wasm-gen@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.8.5.tgz#54840766c2c1002eb64ed1abe720aded714f98bc" + integrity sha512-BCZBT0LURC0CXDzj5FXSc2FPTsxwp3nWcqXQdOZE4U7h7i8FqtFK5Egia6f9raQLpEKT1VL7zr4r3+QX6zArWg== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/ieee754" "1.8.5" + "@webassemblyjs/leb128" "1.8.5" + "@webassemblyjs/utf8" "1.8.5" + +"@webassemblyjs/wasm-opt@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.8.5.tgz#b24d9f6ba50394af1349f510afa8ffcb8a63d264" + integrity sha512-HKo2mO/Uh9A6ojzu7cjslGaHaUU14LdLbGEKqTR7PBKwT6LdPtLLh9fPY33rmr5wcOMrsWDbbdCHq4hQUdd37Q== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-buffer" "1.8.5" + "@webassemblyjs/wasm-gen" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + +"@webassemblyjs/wasm-parser@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.8.5.tgz#21576f0ec88b91427357b8536383668ef7c66b8d" + integrity sha512-pi0SYE9T6tfcMkthwcgCpL0cM9nRYr6/6fjgDtL6q/ZqKHdMWvxitRi5JcZ7RI4SNJJYnYNaWy5UUrHQy998lw== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-api-error" "1.8.5" + "@webassemblyjs/helper-wasm-bytecode" "1.8.5" + "@webassemblyjs/ieee754" "1.8.5" + "@webassemblyjs/leb128" "1.8.5" + "@webassemblyjs/utf8" "1.8.5" + +"@webassemblyjs/wast-parser@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-parser/-/wast-parser-1.8.5.tgz#e10eecd542d0e7bd394f6827c49f3df6d4eefb8c" + integrity sha512-daXC1FyKWHF1i11obK086QRlsMsY4+tIOKgBqI1lxAnkp9xe9YMcgOxm9kLe+ttjs5aWV2KKE1TWJCN57/Btsg== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/floating-point-hex-parser" "1.8.5" + "@webassemblyjs/helper-api-error" "1.8.5" + "@webassemblyjs/helper-code-frame" "1.8.5" + "@webassemblyjs/helper-fsm" "1.8.5" + "@xtuc/long" "4.2.2" + +"@webassemblyjs/wast-printer@1.8.5": + version "1.8.5" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.8.5.tgz#114bbc481fd10ca0e23b3560fa812748b0bae5bc" + integrity sha512-w0U0pD4EhlnvRyeJzBqaVSJAo9w/ce7/WPogeXLzGkO6hzhr4GnQIZ4W4uUt5b9ooAaXPtnXlj0gzsXEOUNYMg== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/wast-parser" "1.8.5" + "@xtuc/long" "4.2.2" + +"@xtuc/ieee754@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" + integrity sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA== + +"@xtuc/long@4.2.2": + version "4.2.2" + resolved "https://registry.yarnpkg.com/@xtuc/long/-/long-4.2.2.tgz#d291c6a4e97989b5c61d9acf396ae4fe133a718d" + integrity sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ== + +abbrev@1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" + integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== + +accepts@~1.3.4, accepts@~1.3.5, accepts@~1.3.7: + version "1.3.7" + resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" + integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== + dependencies: + mime-types "~2.1.24" + negotiator "0.6.2" + +acorn-walk@^6.1.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-6.2.0.tgz#123cb8f3b84c2171f1f7fb252615b1c78a6b1a8c" + integrity sha512-7evsyfH1cLOCdAzZAd43Cic04yKydNx0cF+7tiA19p1XnLLPU4dpCQOqpjqwokFe//vS0QqfqqjCS2JkiIs0cA== + +acorn@^6.0.7, acorn@^6.2.1: + version "6.4.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.0.tgz#b659d2ffbafa24baf5db1cdbb2c94a983ecd2784" + integrity sha512-gac8OEcQ2Li1dxIEWGZzsp2BitJxwkwcOm0zHAJLcPJaVvm58FRnk6RkuLRpU1EujipU2ZFODv2P9DLMfnV8mw== + +address@1.1.2, address@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/address/-/address-1.1.2.tgz#bf1116c9c758c51b7a933d296b72c221ed9428b6" + integrity sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA== + +agentkeepalive@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/agentkeepalive/-/agentkeepalive-2.2.0.tgz#c5d1bd4b129008f1163f236f86e5faea2026e2ef" + integrity sha1-xdG9SxKQCPEWPyNvhuX66iAm4u8= + +aggregate-error@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.0.1.tgz#db2fe7246e536f40d9b5442a39e117d7dd6a24e0" + integrity sha512-quoaXsZ9/BLNae5yiNoUz+Nhkwz83GhWwtYFglcjEQB2NDHCIpApbqXxIFnm4Pq/Nvhrsq5sYJFyohrrxnTGAA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ajv-errors@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/ajv-errors/-/ajv-errors-1.0.1.tgz#f35986aceb91afadec4102fbd85014950cefa64d" + integrity sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ== + +ajv-keywords@^3.1.0, ajv-keywords@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da" + integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== + +ajv@^6.1.0, ajv@^6.10.2, ajv@^6.5.5: + version "6.11.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.11.0.tgz#c3607cbc8ae392d8a5a536f25b21f8e5f3f87fe9" + integrity sha512-nCprB/0syFYy9fVYU1ox1l2KN8S9I+tziH8D4zdZuLT3N6RMlGSGt5FSTpAiHB/Whv8Qs1cWHma1aMKZyaHRKA== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + +algoliasearch@^3.24.5: + version "3.35.1" + resolved "https://registry.yarnpkg.com/algoliasearch/-/algoliasearch-3.35.1.tgz#297d15f534a3507cab2f5dfb996019cac7568f0c" + integrity sha512-K4yKVhaHkXfJ/xcUnil04xiSrB8B8yHZoFEhWNpXg23eiCnqvTZw1tn/SqvdsANlYHLJlKl0qi3I/Q2Sqo7LwQ== + dependencies: + agentkeepalive "^2.2.0" + debug "^2.6.9" + envify "^4.0.0" + es6-promise "^4.1.0" + events "^1.1.0" + foreach "^2.0.5" + global "^4.3.2" + inherits "^2.0.1" + isarray "^2.0.1" + load-script "^1.0.0" + object-keys "^1.0.11" + querystring-es3 "^0.2.1" + reduce "^1.0.1" + semver "^5.1.0" + tunnel-agent "^0.6.0" + +alphanum-sort@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/alphanum-sort/-/alphanum-sort-1.0.2.tgz#97a1119649b211ad33691d9f9f486a8ec9fbe0a3" + integrity sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= + +ansi-colors@^3.0.0: + version "3.2.4" + resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.4.tgz#e3a3da4bfbae6c86a9c285625de124a234026fbf" + integrity sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA== + +ansi-escapes@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-3.2.0.tgz#8780b98ff9dbf5638152d1f1fe5c1d7b4442976b" + integrity sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ== + +ansi-escapes@^4.2.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.0.tgz#a4ce2b33d6b214b7950d8595c212f12ac9cc569d" + integrity sha512-EiYhwo0v255HUL6eDyuLrXEkTi7WwVCLAw+SeOQ7M7qdun1z1pum4DEm/nuqIVbPvi9RPPc9k9LbyBv6H0DwVg== + dependencies: + type-fest "^0.8.1" + +ansi-html@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/ansi-html/-/ansi-html-0.0.7.tgz#813584021962a9e9e6fd039f940d12f56ca7859e" + integrity sha1-gTWEAhliqenm/QOflA0S9WynhZ4= + +ansi-regex@^2.0.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-regex@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.0.tgz#388539f55179bf39339c81af30a654d69f87cb75" + integrity sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg== + +ansi-styles@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + integrity sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4= + +ansi-styles@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.2.1.tgz#90ae75c424d008d2624c5bf29ead3177ebfcf359" + integrity sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA== + dependencies: + "@types/color-name" "^1.1.1" + color-convert "^2.0.1" + +anymatch@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-2.0.0.tgz#bcb24b4f37934d9aa7ac17b4adaf89e7c76ef2eb" + integrity sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw== + dependencies: + micromatch "^3.1.4" + normalize-path "^2.1.1" + +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +aproba@^1.0.3, aproba@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" + integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== + +are-we-there-yet@~1.1.2: + version "1.1.5" + resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" + integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== + dependencies: + delegates "^1.0.0" + readable-stream "^2.0.6" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +arr-diff@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" + integrity sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= + +arr-flatten@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/arr-flatten/-/arr-flatten-1.1.0.tgz#36048bbff4e7b47e136644316c99669ea5ae91f1" + integrity sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg== + +arr-union@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/arr-union/-/arr-union-3.1.0.tgz#e39b09aea9def866a8f206e288af63919bae39c4" + integrity sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= + +array-flatten@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" + integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= + +array-flatten@^2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-2.1.2.tgz#24ef80a28c1a893617e2149b0c6d0d788293b099" + integrity sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ== + +array-union@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39" + integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= + dependencies: + array-uniq "^1.0.1" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array-uniq@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/array-uniq/-/array-uniq-1.0.3.tgz#af6ac877a25cc7f74e058894753858dfdb24fdb6" + integrity sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= + +array-unique@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/array-unique/-/array-unique-0.3.2.tgz#a894b75d4bc4f6cd679ef3244a9fd8f46ae2d428" + integrity sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= + +arrify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" + integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0= + +asn1.js@^4.0.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/asn1.js/-/asn1.js-4.10.1.tgz#b9c2bf5805f1e64aadeed6df3a2bfafb5a73f5a0" + integrity sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw== + dependencies: + bn.js "^4.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +asn1@~0.2.3: + version "0.2.4" + resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" + integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== + dependencies: + safer-buffer "~2.1.0" + +assert-plus@1.0.0, assert-plus@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" + integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= + +assert@^1.1.1: + version "1.5.0" + resolved "https://registry.yarnpkg.com/assert/-/assert-1.5.0.tgz#55c109aaf6e0aefdb3dc4b71240c70bf574b18eb" + integrity sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA== + dependencies: + object-assign "^4.1.1" + util "0.10.3" + +assign-symbols@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/assign-symbols/-/assign-symbols-1.0.0.tgz#59667f41fadd4f20ccbc2bb96b8d4f7f78ec0367" + integrity sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= + +async-each@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf" + integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ== + +async-limiter@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" + integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== + +async@^2.6.2: + version "2.6.3" + resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff" + integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg== + dependencies: + lodash "^4.17.14" + +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= + +atob@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" + integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== + +autocomplete.js@0.36.0: + version "0.36.0" + resolved "https://registry.yarnpkg.com/autocomplete.js/-/autocomplete.js-0.36.0.tgz#94fe775fe64b6cd42e622d076dc7fd26bedd837b" + integrity sha512-jEwUXnVMeCHHutUt10i/8ZiRaCb0Wo+ZyKxeGsYwBDtw6EJHqEeDrq4UwZRD8YBSvp3g6klP678il2eeiVXN2Q== + dependencies: + immediate "^3.2.3" + +autoprefixer@^9.6.1: + version "9.7.4" + resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-9.7.4.tgz#f8bf3e06707d047f0641d87aee8cfb174b2a5378" + integrity sha512-g0Ya30YrMBAEZk60lp+qfX5YQllG+S5W3GYCFvyHTvhOki0AEQJLPEcIuGRsqVwLi8FvXPVtwTGhfr38hVpm0g== + dependencies: + browserslist "^4.8.3" + caniuse-lite "^1.0.30001020" + chalk "^2.4.2" + normalize-range "^0.1.2" + num2fraction "^1.2.2" + postcss "^7.0.26" + postcss-value-parser "^4.0.2" + +aws-sign2@~0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" + integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= + +aws4@^1.8.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" + integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== + +babel-code-frame@^6.22.0: + version "6.26.0" + resolved "https://registry.yarnpkg.com/babel-code-frame/-/babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + integrity sha1-Y/1D99weO7fONZR9uP42mj9Yx0s= + dependencies: + chalk "^1.1.3" + esutils "^2.0.2" + js-tokens "^3.0.2" + +babel-loader@^8.0.6: + version "8.0.6" + resolved "https://registry.yarnpkg.com/babel-loader/-/babel-loader-8.0.6.tgz#e33bdb6f362b03f4bb141a0c21ab87c501b70dfb" + integrity sha512-4BmWKtBOBm13uoUwd08UwjZlaw3O9GWf456R9j+5YykFZ6LUIjIKLc0zEZf+hauxPOJs96C8k6FvYD09vWzhYw== + dependencies: + find-cache-dir "^2.0.0" + loader-utils "^1.0.2" + mkdirp "^0.5.1" + pify "^4.0.1" + +babel-plugin-apply-mdx-type-prop@^1.5.5: + version "1.5.5" + resolved "https://registry.yarnpkg.com/babel-plugin-apply-mdx-type-prop/-/babel-plugin-apply-mdx-type-prop-1.5.5.tgz#b5f6333b445f1ec189949225f9309d67c24cf167" + integrity sha512-yaklz3xE5vFtZpPpYC9lDbTqlC6hq0CjgheiLw3i40lY8vG0DINh+HJ7rq1Gi1g0q/iihwetJ+YFGpUM4YXAGA== + dependencies: + "@babel/helper-plugin-utils" "7.8.0" + "@mdx-js/util" "^1.5.5" + +babel-plugin-dynamic-import-node@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.0.tgz#f00f507bdaa3c3e3ff6e7e5e98d90a7acab96f7f" + integrity sha512-o6qFkpeQEBxcqt0XYlWzAVxNCSCZdUgcR8IRlhD/8DylxjjO4foPcvTW0GGKa/cVt3rvxZ7o5ippJ+/0nvLhlQ== + dependencies: + object.assign "^4.1.0" + +babel-plugin-extract-import-names@^1.5.5: + version "1.5.5" + resolved "https://registry.yarnpkg.com/babel-plugin-extract-import-names/-/babel-plugin-extract-import-names-1.5.5.tgz#34ce3332d2802442286c9cfde6ba8198d5f5e7de" + integrity sha512-F9paxnUtO3vddyOX+vbRa8KrkuovJIFB8KmB/dEICqTUm2331LcGbjCKzZApOri4Igbk9MnYybm2fDsuPJC3vA== + dependencies: + "@babel/helper-plugin-utils" "7.8.0" + +bail@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/bail/-/bail-1.0.5.tgz#b6fa133404a392cbc1f8c4bf63f5953351e7a776" + integrity sha512-xFbRxM1tahm08yHBP16MMjVUAvDaBMD38zsM9EMAUN61omwLmKlOpB/Zku5QkjZ8TZ4vn53pj+t518cH0S03RQ== + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +base64-js@^1.0.2: + version "1.3.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.3.1.tgz#58ece8cb75dd07e71ed08c736abc5fac4dbf8df1" + integrity sha512-mLQ4i2QO1ytvGWFWmcngKO//JXAQueZvwEKtjgQFM4jIK0kU+ytMfplL8j+n5mspOfjHwoAg+9yhb7BwAHm36g== + +base@^0.11.1: + version "0.11.2" + resolved "https://registry.yarnpkg.com/base/-/base-0.11.2.tgz#7bde5ced145b6d551a90db87f83c558b4eb48a8f" + integrity sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg== + dependencies: + cache-base "^1.0.1" + class-utils "^0.3.5" + component-emitter "^1.2.1" + define-property "^1.0.0" + isobject "^3.0.1" + mixin-deep "^1.2.0" + pascalcase "^0.1.1" + +batch@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/batch/-/batch-0.6.1.tgz#dc34314f4e679318093fc760272525f94bf25c16" + integrity sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= + +bcrypt-pbkdf@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" + integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= + dependencies: + tweetnacl "^0.14.3" + +bfj@^6.1.1: + version "6.1.2" + resolved "https://registry.yarnpkg.com/bfj/-/bfj-6.1.2.tgz#325c861a822bcb358a41c78a33b8e6e2086dde7f" + integrity sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw== + dependencies: + bluebird "^3.5.5" + check-types "^8.0.3" + hoopy "^0.1.4" + tryer "^1.0.1" + +big.js@^5.2.2: + version "5.2.2" + resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" + integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== + +binary-extensions@^1.0.0: + version "1.13.1" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-1.13.1.tgz#598afe54755b2868a5330d2aff9d4ebb53209b65" + integrity sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw== + +binary-extensions@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.0.0.tgz#23c0df14f6a88077f5f986c0d167ec03c3d5537c" + integrity sha512-Phlt0plgpIIBOGTT/ehfFnbNlfsDEiqmzE2KRXoX1bLIlir4X/MR+zSyBEkL05ffWgnRSf/DXv+WrUAVr93/ow== + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bluebird@^3.5.5, bluebird@^3.7.1: + version "3.7.2" + resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" + integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== + +bn.js@^4.0.0, bn.js@^4.1.0, bn.js@^4.1.1, bn.js@^4.4.0: + version "4.11.8" + resolved "https://registry.yarnpkg.com/bn.js/-/bn.js-4.11.8.tgz#2cde09eb5ee341f484746bb0309b3253b1b1442f" + integrity sha512-ItfYfPLkWHUjckQCk8xC+LwxgK8NYcXywGigJgSwOP8Y2iyWT4f2vsZnoOXTTbo+o5yXmIUJ4gn5538SO5S3gA== + +body-parser@1.19.0: + version "1.19.0" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" + integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== + dependencies: + bytes "3.1.0" + content-type "~1.0.4" + debug "2.6.9" + depd "~1.1.2" + http-errors "1.7.2" + iconv-lite "0.4.24" + on-finished "~2.3.0" + qs "6.7.0" + raw-body "2.4.0" + type-is "~1.6.17" + +bonjour@^3.5.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/bonjour/-/bonjour-3.5.0.tgz#8e890a183d8ee9a2393b3844c691a42bcf7bc9f5" + integrity sha1-jokKGD2O6aI5OzhExpGkK897yfU= + dependencies: + array-flatten "^2.1.0" + deep-equal "^1.0.1" + dns-equal "^1.0.0" + dns-txt "^2.0.2" + multicast-dns "^6.0.1" + multicast-dns-service-types "^1.1.0" + +boolbase@^1.0.0, boolbase@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" + integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@^2.3.1, braces@^2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-2.3.2.tgz#5979fd3f14cd531565e5fa2df1abfff1dfaee729" + integrity sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w== + dependencies: + arr-flatten "^1.1.0" + array-unique "^0.3.2" + extend-shallow "^2.0.1" + fill-range "^4.0.0" + isobject "^3.0.1" + repeat-element "^1.1.2" + snapdragon "^0.8.1" + snapdragon-node "^2.0.1" + split-string "^3.0.2" + to-regex "^3.0.1" + +braces@^3.0.1, braces@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +brorand@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/brorand/-/brorand-1.1.0.tgz#12c25efe40a45e3c323eb8675a0a0ce57b22371f" + integrity sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= + +browserify-aes@^1.0.0, browserify-aes@^1.0.4: + version "1.2.0" + resolved "https://registry.yarnpkg.com/browserify-aes/-/browserify-aes-1.2.0.tgz#326734642f403dabc3003209853bb70ad428ef48" + integrity sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA== + dependencies: + buffer-xor "^1.0.3" + cipher-base "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.3" + inherits "^2.0.1" + safe-buffer "^5.0.1" + +browserify-cipher@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/browserify-cipher/-/browserify-cipher-1.0.1.tgz#8d6474c1b870bfdabcd3bcfcc1934a10e94f15f0" + integrity sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w== + dependencies: + browserify-aes "^1.0.4" + browserify-des "^1.0.0" + evp_bytestokey "^1.0.0" + +browserify-des@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/browserify-des/-/browserify-des-1.0.2.tgz#3af4f1f59839403572f1c66204375f7a7f703e9c" + integrity sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A== + dependencies: + cipher-base "^1.0.1" + des.js "^1.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +browserify-rsa@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/browserify-rsa/-/browserify-rsa-4.0.1.tgz#21e0abfaf6f2029cf2fafb133567a701d4135524" + integrity sha1-IeCr+vbyApzy+vsTNWenAdQTVSQ= + dependencies: + bn.js "^4.1.0" + randombytes "^2.0.1" + +browserify-sign@^4.0.0: + version "4.0.4" + resolved "https://registry.yarnpkg.com/browserify-sign/-/browserify-sign-4.0.4.tgz#aa4eb68e5d7b658baa6bf6a57e630cbd7a93d298" + integrity sha1-qk62jl17ZYuqa/alfmMMvXqT0pg= + dependencies: + bn.js "^4.1.1" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.2" + elliptic "^6.0.0" + inherits "^2.0.1" + parse-asn1 "^5.0.0" + +browserify-zlib@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/browserify-zlib/-/browserify-zlib-0.2.0.tgz#2869459d9aa3be245fe8fe2ca1f46e2e7f54d73f" + integrity sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA== + dependencies: + pako "~1.0.5" + +browserslist@4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.7.0.tgz#9ee89225ffc07db03409f2fee524dc8227458a17" + integrity sha512-9rGNDtnj+HaahxiVV38Gn8n8Lr8REKsel68v1sPFfIGEK6uSXTY3h9acgiT1dZVtOOUtifo/Dn8daDQ5dUgVsA== + dependencies: + caniuse-lite "^1.0.30000989" + electron-to-chromium "^1.3.247" + node-releases "^1.1.29" + +browserslist@^4.0.0, browserslist@^4.6.4, browserslist@^4.8.3, browserslist@^4.8.5: + version "4.8.6" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.8.6.tgz#96406f3f5f0755d272e27a66f4163ca821590a7e" + integrity sha512-ZHao85gf0eZ0ESxLfCp73GG9O/VTytYDIkIiZDlURppLTI9wErSM/5yAKEq6rcUdxBLjMELmrYUJGg5sxGKMHg== + dependencies: + caniuse-lite "^1.0.30001023" + electron-to-chromium "^1.3.341" + node-releases "^1.1.47" + +buffer-from@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.1.tgz#32713bc028f75c02fdb710d7c7bcec1f2c6070ef" + integrity sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A== + +buffer-indexof@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/buffer-indexof/-/buffer-indexof-1.1.1.tgz#52fabcc6a606d1a00302802648ef68f639da268c" + integrity sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g== + +buffer-json@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/buffer-json/-/buffer-json-2.0.0.tgz#f73e13b1e42f196fe2fd67d001c7d7107edd7c23" + integrity sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw== + +buffer-xor@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9" + integrity sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= + +buffer@^4.3.0: + version "4.9.2" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-4.9.2.tgz#230ead344002988644841ab0244af8c44bbe3ef8" + integrity sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg== + dependencies: + base64-js "^1.0.2" + ieee754 "^1.1.4" + isarray "^1.0.0" + +builtin-status-codes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz#85982878e21b98e1c66425e03d0174788f569ee8" + integrity sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= + +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= + +bytes@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" + integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== + +cacache@^12.0.2, cacache@^12.0.3: + version "12.0.3" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-12.0.3.tgz#be99abba4e1bf5df461cd5a2c1071fc432573390" + integrity sha512-kqdmfXEGFepesTuROHMs3MpFLWrPkSSpRqOw80RCflZXy/khxaArvFrQ7uJxSUduzAufc6G0g1VUCOZXxWavPw== + dependencies: + bluebird "^3.5.5" + chownr "^1.1.1" + figgy-pudding "^3.5.1" + glob "^7.1.4" + graceful-fs "^4.1.15" + infer-owner "^1.0.3" + lru-cache "^5.1.1" + mississippi "^3.0.0" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + promise-inflight "^1.0.1" + rimraf "^2.6.3" + ssri "^6.0.1" + unique-filename "^1.1.1" + y18n "^4.0.0" + +cacache@^13.0.1: + version "13.0.1" + resolved "https://registry.yarnpkg.com/cacache/-/cacache-13.0.1.tgz#a8000c21697089082f85287a1aec6e382024a71c" + integrity sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w== + dependencies: + chownr "^1.1.2" + figgy-pudding "^3.5.1" + fs-minipass "^2.0.0" + glob "^7.1.4" + graceful-fs "^4.2.2" + infer-owner "^1.0.4" + lru-cache "^5.1.1" + minipass "^3.0.0" + minipass-collect "^1.0.2" + minipass-flush "^1.0.5" + minipass-pipeline "^1.2.2" + mkdirp "^0.5.1" + move-concurrently "^1.0.1" + p-map "^3.0.0" + promise-inflight "^1.0.1" + rimraf "^2.7.1" + ssri "^7.0.0" + unique-filename "^1.1.1" + +cache-base@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cache-base/-/cache-base-1.0.1.tgz#0a7f46416831c8b662ee36fe4e7c59d76f666ab2" + integrity sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ== + dependencies: + collection-visit "^1.0.0" + component-emitter "^1.2.1" + get-value "^2.0.6" + has-value "^1.0.0" + isobject "^3.0.1" + set-value "^2.0.0" + to-object-path "^0.3.0" + union-value "^1.0.0" + unset-value "^1.0.0" + +cache-loader@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cache-loader/-/cache-loader-4.1.0.tgz#9948cae353aec0a1fcb1eafda2300816ec85387e" + integrity sha512-ftOayxve0PwKzBF/GLsZNC9fJBXl8lkZE3TOsjkboHfVHVkL39iUEs1FO07A33mizmci5Dudt38UZrrYXDtbhw== + dependencies: + buffer-json "^2.0.0" + find-cache-dir "^3.0.0" + loader-utils "^1.2.3" + mkdirp "^0.5.1" + neo-async "^2.6.1" + schema-utils "^2.0.0" + +call-me-maybe@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-me-maybe/-/call-me-maybe-1.0.1.tgz#26d208ea89e37b5cbde60250a15f031c16a4d66b" + integrity sha1-JtII6onje1y95gJQoV8DHBak1ms= + +caller-callsite@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-callsite/-/caller-callsite-2.0.0.tgz#847e0fce0a223750a9a027c54b33731ad3154134" + integrity sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= + dependencies: + callsites "^2.0.0" + +caller-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/caller-path/-/caller-path-2.0.0.tgz#468f83044e369ab2010fac5f06ceee15bb2cb1f4" + integrity sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= + dependencies: + caller-callsite "^2.0.0" + +callsites@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-2.0.0.tgz#06eb84f00eea413da86affefacbffb36093b3c50" + integrity sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +camel-case@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/camel-case/-/camel-case-3.0.0.tgz#ca3c3688a4e9cf3a4cda777dc4dcbc713249cf73" + integrity sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= + dependencies: + no-case "^2.2.0" + upper-case "^1.1.1" + +camelcase-css@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" + integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +caniuse-api@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/caniuse-api/-/caniuse-api-3.0.0.tgz#5e4d90e2274961d46291997df599e3ed008ee4c0" + integrity sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw== + dependencies: + browserslist "^4.0.0" + caniuse-lite "^1.0.0" + lodash.memoize "^4.1.2" + lodash.uniq "^4.5.0" + +caniuse-lite@^1.0.0, caniuse-lite@^1.0.30000981, caniuse-lite@^1.0.30000989, caniuse-lite@^1.0.30001020, caniuse-lite@^1.0.30001023: + version "1.0.30001027" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001027.tgz#283e2ef17d94889cc216a22c6f85303d78ca852d" + integrity sha512-7xvKeErvXZFtUItTHgNtLgS9RJpVnwBlWX8jSo/BO8VsF6deszemZSkJJJA1KOKrXuzZH4WALpAJdq5EyfgMLg== + +caseless@~0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" + integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= + +ccount@^1.0.3: + version "1.0.5" + resolved "https://registry.yarnpkg.com/ccount/-/ccount-1.0.5.tgz#ac82a944905a65ce204eb03023157edf29425c17" + integrity sha512-MOli1W+nfbPLlKEhInaxhRdp7KVLFxLN5ykwzHgLsLI3H3gs5jjFAK4Eoj3OzzcxCtumDaI8onoVDeQyWaNTkw== + +chalk@2.4.2, chalk@^2.0.0, chalk@^2.4.1, chalk@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" + integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== + dependencies: + ansi-styles "^3.2.1" + escape-string-regexp "^1.0.5" + supports-color "^5.3.0" + +chalk@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + integrity sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg= + dependencies: + ansi-styles "^2.2.1" + escape-string-regexp "^1.0.2" + has-ansi "^2.0.0" + strip-ansi "^3.0.0" + supports-color "^2.0.0" + +chalk@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-3.0.0.tgz#3f73c2bf526591f574cc492c51e2456349f844e4" + integrity sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +check-types@^8.0.3: + version "8.0.3" + resolved "https://registry.yarnpkg.com/check-types/-/check-types-8.0.3.tgz#3356cca19c889544f2d7a95ed49ce508a0ecf552" + integrity sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ== + +cheerio@^0.22.0: + version "0.22.0" + resolved "https://registry.yarnpkg.com/cheerio/-/cheerio-0.22.0.tgz#a9baa860a3f9b595a6b81b1a86873121ed3a269e" + integrity sha1-qbqoYKP5tZWmuBsahocxIe06Jp4= + dependencies: + css-select "~1.2.0" + dom-serializer "~0.1.0" + entities "~1.1.1" + htmlparser2 "^3.9.1" + lodash.assignin "^4.0.9" + lodash.bind "^4.1.4" + lodash.defaults "^4.0.1" + lodash.filter "^4.4.0" + lodash.flatten "^4.2.0" + lodash.foreach "^4.3.0" + lodash.map "^4.4.0" + lodash.merge "^4.4.0" + lodash.pick "^4.2.1" + lodash.reduce "^4.4.0" + lodash.reject "^4.4.0" + lodash.some "^4.4.0" + +chokidar@^2.0.2, chokidar@^2.0.4, chokidar@^2.1.8: + version "2.1.8" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" + integrity sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg== + dependencies: + anymatch "^2.0.0" + async-each "^1.0.1" + braces "^2.3.2" + glob-parent "^3.1.0" + inherits "^2.0.3" + is-binary-path "^1.0.0" + is-glob "^4.0.0" + normalize-path "^3.0.0" + path-is-absolute "^1.0.0" + readdirp "^2.2.1" + upath "^1.1.1" + optionalDependencies: + fsevents "^1.2.7" + +chokidar@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.3.1.tgz#c84e5b3d18d9a4d77558fef466b1bf16bbeb3450" + integrity sha512-4QYCEWOcK3OJrxwvyyAOxFuhpvOVCYkr33LPfFNBjAD/w3sEzWsp2BUOkI4l9bHvWioAd0rc6NlHUOEaWkTeqg== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.3.0" + optionalDependencies: + fsevents "~2.1.2" + +chownr@^1.1.1, chownr@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + +chrome-trace-event@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.2.tgz#234090ee97c7d4ad1a2c4beae27505deffc608a4" + integrity sha512-9e/zx1jw7B4CO+c/RXoCsfg/x1AfUBioy4owYH0bJprEYAx5hRFLRhWBqHAG57D0ZM4H7vxbP7bPe0VwhQRYDQ== + dependencies: + tslib "^1.9.0" + +ci-info@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" + integrity sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A== + +cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/cipher-base/-/cipher-base-1.0.4.tgz#8760e4ecc272f4c363532f926d874aae2c1397de" + integrity sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +class-utils@^0.3.5: + version "0.3.6" + resolved "https://registry.yarnpkg.com/class-utils/-/class-utils-0.3.6.tgz#f93369ae8b9a7ce02fd41faad0ca83033190c463" + integrity sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg== + dependencies: + arr-union "^3.1.0" + define-property "^0.2.5" + isobject "^3.0.0" + static-extend "^0.1.1" + +classnames@^2.2.5, classnames@^2.2.6: + version "2.2.6" + resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce" + integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q== + +clean-css@^4.2.1: + version "4.2.3" + resolved "https://registry.yarnpkg.com/clean-css/-/clean-css-4.2.3.tgz#507b5de7d97b48ee53d84adb0160ff6216380f78" + integrity sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA== + dependencies: + source-map "~0.6.0" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-cursor@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" + integrity sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= + dependencies: + restore-cursor "^2.0.0" + +cli-width@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-2.2.0.tgz#ff19ede8a9a5e579324147b0c11f0fbcbabed639" + integrity sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk= + +clipboard@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/clipboard/-/clipboard-2.0.4.tgz#836dafd66cf0fea5d71ce5d5b0bf6e958009112d" + integrity sha512-Vw26VSLRpJfBofiVaFb/I8PVfdI1OxKcYShe6fm0sP/DtmiWQNCjhM/okTvdCo0G+lMMm1rMYbk4IK4x1X+kgQ== + dependencies: + good-listener "^1.2.2" + select "^1.1.2" + tiny-emitter "^2.0.0" + +cliui@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-4.1.0.tgz#348422dbe82d800b3022eef4f6ac10bf2e4d1b49" + integrity sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ== + dependencies: + string-width "^2.1.1" + strip-ansi "^4.0.0" + wrap-ansi "^2.0.0" + +coa@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/coa/-/coa-2.0.2.tgz#43f6c21151b4ef2bf57187db0d73de229e3e7ec3" + integrity sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA== + dependencies: + "@types/q" "^1.5.1" + chalk "^2.4.1" + q "^1.1.2" + +code-point-at@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" + integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= + +collapse-white-space@^1.0.0, collapse-white-space@^1.0.2: + version "1.0.6" + resolved "https://registry.yarnpkg.com/collapse-white-space/-/collapse-white-space-1.0.6.tgz#e63629c0016665792060dbbeb79c42239d2c5287" + integrity sha512-jEovNnrhMuqyCcjfEJA56v0Xq8SkIoPKDyaHahwo3POf4qcSXqMYuwNcOTzp74vTsR9Tn08z4MxWqAhcekogkQ== + +collection-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/collection-visit/-/collection-visit-1.0.0.tgz#4bc0373c164bc3291b4d368c829cf1a80a59dca0" + integrity sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= + dependencies: + map-visit "^1.0.0" + object-visit "^1.0.0" + +color-convert@^1.9.0, color-convert@^1.9.1: + version "1.9.3" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@^1.0.0, color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +color-string@^1.5.2: + version "1.5.3" + resolved "https://registry.yarnpkg.com/color-string/-/color-string-1.5.3.tgz#c9bbc5f01b58b5492f3d6857459cb6590ce204cc" + integrity sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw== + dependencies: + color-name "^1.0.0" + simple-swizzle "^0.2.2" + +color@^3.0.0: + version "3.1.2" + resolved "https://registry.yarnpkg.com/color/-/color-3.1.2.tgz#68148e7f85d41ad7649c5fa8c8106f098d229e10" + integrity sha512-vXTJhHebByxZn3lDvDJYw4lR5+uB3vuoHsuYA5AKuxRVn5wzzIfQKGLBmgdVRHKTJYeK5rvJcHnrd0Li49CFpg== + dependencies: + color-convert "^1.9.1" + color-string "^1.5.2" + +combined-stream@^1.0.6, combined-stream@~1.0.6: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + +comma-separated-tokens@^1.0.0: + version "1.0.8" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" + integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== + +commander@^2.18.0, commander@^2.20.0: + version "2.20.3" + resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" + integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== + +commander@^4.0.0, commander@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" + integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= + +component-emitter@^1.2.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0" + integrity sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg== + +compressible@~2.0.16: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.7.4.tgz#95523eff170ca57c29a0ca41e6fe131f41e5bb8f" + integrity sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ== + dependencies: + accepts "~1.3.5" + bytes "3.0.0" + compressible "~2.0.16" + debug "2.6.9" + on-headers "~1.0.2" + safe-buffer "5.1.2" + vary "~1.1.2" + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +concat-stream@^1.5.0: + version "1.6.2" + resolved "https://registry.yarnpkg.com/concat-stream/-/concat-stream-1.6.2.tgz#904bdf194cd3122fc675c77fc4ac3d4ff0fd1a34" + integrity sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw== + dependencies: + buffer-from "^1.0.0" + inherits "^2.0.3" + readable-stream "^2.2.2" + typedarray "^0.0.6" + +connect-history-api-fallback@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz#8b32089359308d111115d81cad3fceab888f97bc" + integrity sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg== + +consola@^2.10.0: + version "2.11.3" + resolved "https://registry.yarnpkg.com/consola/-/consola-2.11.3.tgz#f7315836224c143ac5094b47fd4c816c2cd1560e" + integrity sha512-aoW0YIIAmeftGR8GSpw6CGQluNdkWMWh3yEFjH/hmynTYnMtibXszii3lxCXmk8YxJtI3FAK5aTiquA5VH68Gw== + +console-browserify@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/console-browserify/-/console-browserify-1.2.0.tgz#67063cef57ceb6cf4993a2ab3a55840ae8c49336" + integrity sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA== + +console-control-strings@^1.0.0, console-control-strings@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" + integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= + +constants-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/constants-browserify/-/constants-browserify-1.0.0.tgz#c20b96d8c617748aaf1c16021760cd27fcb8cb75" + integrity sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= + +content-disposition@0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" + integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== + dependencies: + safe-buffer "5.1.2" + +content-type@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" + integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== + +convert-source-map@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" + integrity sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA== + dependencies: + safe-buffer "~5.1.1" + +cookie-signature@1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" + integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= + +cookie@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" + integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== + +copy-concurrently@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/copy-concurrently/-/copy-concurrently-1.0.5.tgz#92297398cae34937fcafd6ec8139c18051f0b5e0" + integrity sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A== + dependencies: + aproba "^1.1.1" + fs-write-stream-atomic "^1.0.8" + iferr "^0.1.5" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.0" + +copy-descriptor@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/copy-descriptor/-/copy-descriptor-0.1.1.tgz#676f6eb3c39997c2ee1ac3a924fd6124748f578d" + integrity sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= + +copy-webpack-plugin@^5.0.5: + version "5.1.1" + resolved "https://registry.yarnpkg.com/copy-webpack-plugin/-/copy-webpack-plugin-5.1.1.tgz#5481a03dea1123d88a988c6ff8b78247214f0b88" + integrity sha512-P15M5ZC8dyCjQHWwd4Ia/dm0SgVvZJMYeykVIVYXbGyqO4dWB5oyPHp9i7wjwo5LhtlhKbiBCdS2NvM07Wlybg== + dependencies: + cacache "^12.0.3" + find-cache-dir "^2.1.0" + glob-parent "^3.1.0" + globby "^7.1.1" + is-glob "^4.0.1" + loader-utils "^1.2.3" + minimatch "^3.0.4" + normalize-path "^3.0.0" + p-limit "^2.2.1" + schema-utils "^1.0.0" + serialize-javascript "^2.1.2" + webpack-log "^2.0.0" + +core-js-compat@^3.6.2: + version "3.6.4" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.6.4.tgz#938476569ebb6cda80d339bcf199fae4f16fff17" + integrity sha512-zAa3IZPvsJ0slViBQ2z+vgyyTuhd3MFn1rBQjZSKVEgB0UMYhUkCj9jJUVPgGTGqWvsBVmfnruXgTcNyTlEiSA== + dependencies: + browserslist "^4.8.3" + semver "7.0.0" + +core-js@^2.6.5: + version "2.6.11" + resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c" + integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg== + +core-util-is@1.0.2, core-util-is@~1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" + integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= + +cosmiconfig@^5.0.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a" + integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA== + dependencies: + import-fresh "^2.0.0" + is-directory "^0.3.1" + js-yaml "^3.13.1" + parse-json "^4.0.0" + +create-ecdh@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/create-ecdh/-/create-ecdh-4.0.3.tgz#c9111b6f33045c4697f144787f9254cdc77c45ff" + integrity sha512-GbEHQPMOswGpKXM9kCWVrremUcBmjteUaQ01T9rkKCPDXfUHX0IoP9LpHYo2NPFampa4e+/pFDc3jQdxrxQLaw== + dependencies: + bn.js "^4.1.0" + elliptic "^6.0.0" + +create-hash@^1.1.0, create-hash@^1.1.2: + version "1.2.0" + resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196" + integrity sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg== + dependencies: + cipher-base "^1.0.1" + inherits "^2.0.1" + md5.js "^1.3.4" + ripemd160 "^2.0.1" + sha.js "^2.4.0" + +create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: + version "1.1.7" + resolved "https://registry.yarnpkg.com/create-hmac/-/create-hmac-1.1.7.tgz#69170c78b3ab957147b2b8b04572e47ead2243ff" + integrity sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg== + dependencies: + cipher-base "^1.0.3" + create-hash "^1.1.0" + inherits "^2.0.1" + ripemd160 "^2.0.0" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +cross-spawn@6.0.5, cross-spawn@^6.0.0: + version "6.0.5" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" + integrity sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ== + dependencies: + nice-try "^1.0.4" + path-key "^2.0.1" + semver "^5.5.0" + shebang-command "^1.2.0" + which "^1.2.9" + +cross-spawn@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.1.tgz#0ab56286e0f7c24e153d04cc2aa027e43a9a5d14" + integrity sha512-u7v4o84SwFpD32Z8IIcPZ6z1/ie24O6RU3RbtL5Y316l3KuHVPx9ItBgWQ6VlfAFnRnTtMUrsQ9MUUTuEZjogg== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +crypto-browserify@^3.11.0: + version "3.12.0" + resolved "https://registry.yarnpkg.com/crypto-browserify/-/crypto-browserify-3.12.0.tgz#396cf9f3137f03e4b8e532c58f698254e00f80ec" + integrity sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg== + dependencies: + browserify-cipher "^1.0.0" + browserify-sign "^4.0.0" + create-ecdh "^4.0.0" + create-hash "^1.1.0" + create-hmac "^1.1.0" + diffie-hellman "^5.0.0" + inherits "^2.0.1" + pbkdf2 "^3.0.3" + public-encrypt "^4.0.0" + randombytes "^2.0.0" + randomfill "^1.0.3" + +css-blank-pseudo@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz#dfdefd3254bf8a82027993674ccf35483bfcb3c5" + integrity sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w== + dependencies: + postcss "^7.0.5" + +css-color-names@0.0.4, css-color-names@^0.0.4: + version "0.0.4" + resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" + integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= + +css-declaration-sorter@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz#c198940f63a76d7e36c1e71018b001721054cb22" + integrity sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA== + dependencies: + postcss "^7.0.1" + timsort "^0.3.0" + +css-has-pseudo@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz#3c642ab34ca242c59c41a125df9105841f6966ee" + integrity sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ== + dependencies: + postcss "^7.0.6" + postcss-selector-parser "^5.0.0-rc.4" + +css-loader@^3.2.0: + version "3.4.2" + resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-3.4.2.tgz#d3fdb3358b43f233b78501c5ed7b1c6da6133202" + integrity sha512-jYq4zdZT0oS0Iykt+fqnzVLRIeiPWhka+7BqPn+oSIpWJAHak5tmB/WZrJ2a21JhCeFyNnnlroSl8c+MtVndzA== + dependencies: + camelcase "^5.3.1" + cssesc "^3.0.0" + icss-utils "^4.1.1" + loader-utils "^1.2.3" + normalize-path "^3.0.0" + postcss "^7.0.23" + postcss-modules-extract-imports "^2.0.0" + postcss-modules-local-by-default "^3.0.2" + postcss-modules-scope "^2.1.1" + postcss-modules-values "^3.0.0" + postcss-value-parser "^4.0.2" + schema-utils "^2.6.0" + +css-prefers-color-scheme@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz#6f830a2714199d4f0d0d0bb8a27916ed65cff1f4" + integrity sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg== + dependencies: + postcss "^7.0.5" + +css-select-base-adapter@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz#3b2ff4972cc362ab88561507a95408a1432135d7" + integrity sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w== + +css-select@^1.1.0, css-select@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-1.2.0.tgz#2b3a110539c5355f1cd8d314623e870b121ec858" + integrity sha1-KzoRBTnFNV8c2NMUYj6HCxIeyFg= + dependencies: + boolbase "~1.0.0" + css-what "2.1" + domutils "1.5.1" + nth-check "~1.0.1" + +css-select@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/css-select/-/css-select-2.1.0.tgz#6a34653356635934a81baca68d0255432105dbef" + integrity sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ== + dependencies: + boolbase "^1.0.0" + css-what "^3.2.1" + domutils "^1.7.0" + nth-check "^1.0.2" + +css-tree@1.0.0-alpha.37: + version "1.0.0-alpha.37" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-1.0.0-alpha.37.tgz#98bebd62c4c1d9f960ec340cf9f7522e30709a22" + integrity sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg== + dependencies: + mdn-data "2.0.4" + source-map "^0.6.1" + +css-unit-converter@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/css-unit-converter/-/css-unit-converter-1.1.1.tgz#d9b9281adcfd8ced935bdbaba83786897f64e996" + integrity sha1-2bkoGtz9jO2TW9urqDeGiX9k6ZY= + +css-what@2.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-2.1.3.tgz#a6d7604573365fe74686c3f311c56513d88285f2" + integrity sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg== + +css-what@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/css-what/-/css-what-3.2.1.tgz#f4a8f12421064621b456755e34a03a2c22df5da1" + integrity sha512-WwOrosiQTvyms+Ti5ZC5vGEK0Vod3FTt1ca+payZqvKuGJF+dq7bG63DstxtN0dpm6FxY27a/zS3Wten+gEtGw== + +cssdb@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/cssdb/-/cssdb-4.4.0.tgz#3bf2f2a68c10f5c6a08abd92378331ee803cddb0" + integrity sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ== + +cssesc@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-2.0.0.tgz#3b13bd1bb1cb36e1bcb5a4dcd27f54c5dcb35703" + integrity sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg== + +cssesc@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cssesc/-/cssesc-3.0.0.tgz#37741919903b868565e1c09ea747445cd18983ee" + integrity sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg== + +cssnano-preset-default@^4.0.7: + version "4.0.7" + resolved "https://registry.yarnpkg.com/cssnano-preset-default/-/cssnano-preset-default-4.0.7.tgz#51ec662ccfca0f88b396dcd9679cdb931be17f76" + integrity sha512-x0YHHx2h6p0fCl1zY9L9roD7rnlltugGu7zXSKQx6k2rYw0Hi3IqxcoAGF7u9Q5w1nt7vK0ulxV8Lo+EvllGsA== + dependencies: + css-declaration-sorter "^4.0.1" + cssnano-util-raw-cache "^4.0.1" + postcss "^7.0.0" + postcss-calc "^7.0.1" + postcss-colormin "^4.0.3" + postcss-convert-values "^4.0.1" + postcss-discard-comments "^4.0.2" + postcss-discard-duplicates "^4.0.2" + postcss-discard-empty "^4.0.1" + postcss-discard-overridden "^4.0.1" + postcss-merge-longhand "^4.0.11" + postcss-merge-rules "^4.0.3" + postcss-minify-font-values "^4.0.2" + postcss-minify-gradients "^4.0.2" + postcss-minify-params "^4.0.2" + postcss-minify-selectors "^4.0.2" + postcss-normalize-charset "^4.0.1" + postcss-normalize-display-values "^4.0.2" + postcss-normalize-positions "^4.0.2" + postcss-normalize-repeat-style "^4.0.2" + postcss-normalize-string "^4.0.2" + postcss-normalize-timing-functions "^4.0.2" + postcss-normalize-unicode "^4.0.1" + postcss-normalize-url "^4.0.1" + postcss-normalize-whitespace "^4.0.2" + postcss-ordered-values "^4.1.2" + postcss-reduce-initial "^4.0.3" + postcss-reduce-transforms "^4.0.2" + postcss-svgo "^4.0.2" + postcss-unique-selectors "^4.0.1" + +cssnano-util-get-arguments@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz#ed3a08299f21d75741b20f3b81f194ed49cc150f" + integrity sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= + +cssnano-util-get-match@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz#c0e4ca07f5386bb17ec5e52250b4f5961365156d" + integrity sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= + +cssnano-util-raw-cache@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz#b26d5fd5f72a11dfe7a7846fb4c67260f96bf282" + integrity sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA== + dependencies: + postcss "^7.0.0" + +cssnano-util-same-parent@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz#574082fb2859d2db433855835d9a8456ea18bbf3" + integrity sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q== + +cssnano@^4.1.10: + version "4.1.10" + resolved "https://registry.yarnpkg.com/cssnano/-/cssnano-4.1.10.tgz#0ac41f0b13d13d465487e111b778d42da631b8b2" + integrity sha512-5wny+F6H4/8RgNlaqab4ktc3e0/blKutmq8yNlBFXA//nSFFAqAngjNVRzUvCgYROULmZZUoosL/KSoZo5aUaQ== + dependencies: + cosmiconfig "^5.0.0" + cssnano-preset-default "^4.0.7" + is-resolvable "^1.0.0" + postcss "^7.0.0" + +csso@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/csso/-/csso-4.0.2.tgz#e5f81ab3a56b8eefb7f0092ce7279329f454de3d" + integrity sha512-kS7/oeNVXkHWxby5tHVxlhjizRCSv8QdU7hB2FpdAibDU8FjTAolhNjKNTiLzXtUrKT6HwClE81yXwEk1309wg== + dependencies: + css-tree "1.0.0-alpha.37" + +cyclist@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/cyclist/-/cyclist-1.0.1.tgz#596e9698fd0c80e12038c2b82d6eb1b35b6224d9" + integrity sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= + +dashdash@^1.12.0: + version "1.14.1" + resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" + integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= + dependencies: + assert-plus "^1.0.0" + +debug@2.6.9, debug@^2.2.0, debug@^2.3.3, debug@^2.6.0, debug@^2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + +debug@^3.0.0, debug@^3.1.1, debug@^3.2.5, debug@^3.2.6: + version "3.2.6" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.6.tgz#e83d17de16d8a7efb7717edbe5fb10135eee629b" + integrity sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.0, debug@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.1.1.tgz#3b72260255109c6b589cee050f1d516139664791" + integrity sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw== + dependencies: + ms "^2.1.1" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decode-uri-component@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" + integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= + +deep-equal@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.1.1.tgz#b5c98c942ceffaf7cb051e24e1434a25a2e6076a" + integrity sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g== + dependencies: + is-arguments "^1.0.4" + is-date-object "^1.0.1" + is-regex "^1.0.4" + object-is "^1.0.1" + object-keys "^1.1.1" + regexp.prototype.flags "^1.2.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +default-gateway@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/default-gateway/-/default-gateway-4.2.0.tgz#167104c7500c2115f6dd69b0a536bb8ed720552b" + integrity sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA== + dependencies: + execa "^1.0.0" + ip-regex "^2.1.0" + +define-properties@^1.1.2, define-properties@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1" + integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ== + dependencies: + object-keys "^1.0.12" + +define-property@^0.2.5: + version "0.2.5" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-0.2.5.tgz#c35b1ef918ec3c990f9a5bc57be04aacec5c8116" + integrity sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= + dependencies: + is-descriptor "^0.1.0" + +define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-1.0.0.tgz#769ebaaf3f4a63aad3af9e8d304c9bbe79bfb0e6" + integrity sha1-dp66rz9KY6rTr56NMEybvnm/sOY= + dependencies: + is-descriptor "^1.0.0" + +define-property@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/define-property/-/define-property-2.0.2.tgz#d459689e8d654ba77e02a817f8710d702cb16e9d" + integrity sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ== + dependencies: + is-descriptor "^1.0.2" + isobject "^3.0.1" + +del@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/del/-/del-4.1.1.tgz#9e8f117222ea44a31ff3a156c049b99052a9f0b4" + integrity sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ== + dependencies: + "@types/glob" "^7.1.1" + globby "^6.1.0" + is-path-cwd "^2.0.0" + is-path-in-cwd "^2.0.0" + p-map "^2.0.0" + pify "^4.0.1" + rimraf "^2.6.3" + +del@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/del/-/del-5.1.0.tgz#d9487c94e367410e6eff2925ee58c0c84a75b3a7" + integrity sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA== + dependencies: + globby "^10.0.1" + graceful-fs "^4.2.2" + is-glob "^4.0.1" + is-path-cwd "^2.2.0" + is-path-inside "^3.0.1" + p-map "^3.0.0" + rimraf "^3.0.0" + slash "^3.0.0" + +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= + +delegate@^3.1.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/delegate/-/delegate-3.2.0.tgz#b66b71c3158522e8ab5744f720d8ca0c2af59166" + integrity sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw== + +delegates@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" + integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= + +depd@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" + integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= + +des.js@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/des.js/-/des.js-1.0.1.tgz#5382142e1bdc53f85d86d53e5f4aa7deb91e0843" + integrity sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA== + dependencies: + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + +destroy@~1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" + integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= + +detab@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.2.tgz#074970d1a807b045d0258a4235df5928dd683561" + integrity sha512-Q57yPrxScy816TTE1P/uLRXLDKjXhvYTbfxS/e6lPD+YrqghbsMlGB9nQzj/zVtSPaF0DFPSdO916EWO4sQUyQ== + dependencies: + repeat-string "^1.5.4" + +detab@^2.0.0: + version "2.0.3" + resolved "https://registry.yarnpkg.com/detab/-/detab-2.0.3.tgz#33e5dd74d230501bd69985a0d2b9a3382699a130" + integrity sha512-Up8P0clUVwq0FnFjDclzZsy9PadzRn5FFxrr47tQQvMHqyiFYVbpH8oXDzWtF0Q7pYy3l+RPmtBl+BsFF6wH0A== + dependencies: + repeat-string "^1.5.4" + +detect-libc@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-1.0.3.tgz#fa137c4bd698edf55cd5cd02ac559f91a4c4ba9b" + integrity sha1-+hN8S9aY7fVc1c0CrFWfkaTEups= + +detect-node@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/detect-node/-/detect-node-2.0.4.tgz#014ee8f8f669c5c58023da64b8179c083a28c46c" + integrity sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw== + +detect-port-alt@1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/detect-port-alt/-/detect-port-alt-1.1.6.tgz#24707deabe932d4a3cf621302027c2b266568275" + integrity sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q== + dependencies: + address "^1.0.1" + debug "^2.6.0" + +diffie-hellman@^5.0.0: + version "5.0.3" + resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" + integrity sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg== + dependencies: + bn.js "^4.1.0" + miller-rabin "^4.0.0" + randombytes "^2.0.0" + +dir-glob@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.0.0.tgz#0b205d2b6aef98238ca286598a8204d29d0a0034" + integrity sha512-37qirFDz8cA5fimp9feo43fSuRo2gHwaIn6dXL8Ber1dGwUosDrGZeCCXq57WnIqE4aQ+u3eQZzsk1yOzhdwag== + dependencies: + arrify "^1.0.1" + path-type "^3.0.0" + +dir-glob@^2.0.0: + version "2.2.2" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-2.2.2.tgz#fa09f0694153c8918b18ba0deafae94769fc50c4" + integrity sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw== + dependencies: + path-type "^3.0.0" + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +dns-equal@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/dns-equal/-/dns-equal-1.0.0.tgz#b39e7f1da6eb0a75ba9c17324b34753c47e0654d" + integrity sha1-s55/HabrCnW6nBcySzR1PEfgZU0= + +dns-packet@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/dns-packet/-/dns-packet-1.3.1.tgz#12aa426981075be500b910eedcd0b47dd7deda5a" + integrity sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg== + dependencies: + ip "^1.1.0" + safe-buffer "^5.0.1" + +dns-txt@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/dns-txt/-/dns-txt-2.0.2.tgz#b91d806f5d27188e4ab3e7d107d881a1cc4642b6" + integrity sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= + dependencies: + buffer-indexof "^1.0.0" + +docsearch.js@^2.6.3: + version "2.6.3" + resolved "https://registry.yarnpkg.com/docsearch.js/-/docsearch.js-2.6.3.tgz#57cb4600d3b6553c677e7cbbe6a734593e38625d" + integrity sha512-GN+MBozuyz664ycpZY0ecdQE0ND/LSgJKhTLA0/v3arIS3S1Rpf2OJz6A35ReMsm91V5apcmzr5/kM84cvUg+A== + dependencies: + algoliasearch "^3.24.5" + autocomplete.js "0.36.0" + hogan.js "^3.0.2" + request "^2.87.0" + stack-utils "^1.0.1" + to-factory "^1.0.0" + zepto "^1.2.0" + +dom-converter@^0.2: + version "0.2.0" + resolved "https://registry.yarnpkg.com/dom-converter/-/dom-converter-0.2.0.tgz#6721a9daee2e293682955b6afe416771627bb768" + integrity sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA== + dependencies: + utila "~0.4" + +dom-serializer@0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.2.2.tgz#1afb81f533717175d478655debc5e332d9f9bb51" + integrity sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g== + dependencies: + domelementtype "^2.0.1" + entities "^2.0.0" + +dom-serializer@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-serializer/-/dom-serializer-0.1.1.tgz#1ec4059e284babed36eec2941d4a970a189ce7c0" + integrity sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA== + dependencies: + domelementtype "^1.3.0" + entities "^1.1.1" + +dom-walk@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018" + integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg= + +domain-browser@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/domain-browser/-/domain-browser-1.2.0.tgz#3d31f50191a6749dd1375a7f522e823d42e54eda" + integrity sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA== + +domelementtype@1, domelementtype@^1.3.0, domelementtype@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-1.3.1.tgz#d048c44b37b0d10a7f2a3d5fee3f4333d790481f" + integrity sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w== + +domelementtype@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/domelementtype/-/domelementtype-2.0.1.tgz#1f8bdfe91f5a78063274e803b4bdcedf6e94f94d" + integrity sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ== + +domhandler@^2.3.0: + version "2.4.2" + resolved "https://registry.yarnpkg.com/domhandler/-/domhandler-2.4.2.tgz#8805097e933d65e85546f726d60f5eb88b44f803" + integrity sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA== + dependencies: + domelementtype "1" + +domutils@1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.5.1.tgz#dcd8488a26f563d61079e48c9f7b7e32373682cf" + integrity sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8= + dependencies: + dom-serializer "0" + domelementtype "1" + +domutils@^1.5.1, domutils@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-1.7.0.tgz#56ea341e834e06e6748af7a1cb25da67ea9f8c2a" + integrity sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg== + dependencies: + dom-serializer "0" + domelementtype "1" + +dot-prop@^4.1.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57" + integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ== + dependencies: + is-obj "^1.0.0" + +duplexer@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.1.tgz#ace6ff808c1ce66b57d1ebf97977acb02334cfc1" + integrity sha1-rOb/gIwc5mtX0ev5eXessCM0z8E= + +duplexify@^3.4.2, duplexify@^3.6.0: + version "3.7.1" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-3.7.1.tgz#2a4df5317f6ccfd91f86d6fd25d8d8a103b88309" + integrity sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g== + dependencies: + end-of-stream "^1.0.0" + inherits "^2.0.1" + readable-stream "^2.0.0" + stream-shift "^1.0.0" + +ecc-jsbn@~0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" + integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= + dependencies: + jsbn "~0.1.0" + safer-buffer "^2.1.0" + +ee-first@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" + integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= + +ejs@^2.6.1: + version "2.7.4" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-2.7.4.tgz#48661287573dcc53e366c7a1ae52c3a120eec9ba" + integrity sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA== + +ejs@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ejs/-/ejs-3.0.1.tgz#30c8f6ee9948502cc32e85c37a3f8b39b5a614a5" + integrity sha512-cuIMtJwxvzumSAkqaaoGY/L6Fc/t6YvoP9/VIaK0V/CyqKLEQ8sqODmYfy/cjXEdZ9+OOL8TecbJu+1RsofGDw== + +electron-to-chromium@^1.3.247, electron-to-chromium@^1.3.341: + version "1.3.349" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.349.tgz#663f26a69d348a462df47b4d7ab162a2f29bbcb7" + integrity sha512-uEb2zs6EJ6OZIqaMsCSliYVgzE/f7/s1fLWqtvRtHg/v5KBF2xds974fUnyatfxIDgkqzQVwFtam5KExqywx0Q== + +elliptic@^6.0.0: + version "6.5.2" + resolved "https://registry.yarnpkg.com/elliptic/-/elliptic-6.5.2.tgz#05c5678d7173c049d8ca433552224a495d0e3762" + integrity sha512-f4x70okzZbIQl/NSRLkI/+tteV/9WqL98zx+SQ69KbXxmVrmjwsNUPn/gYJJ0sHvEak24cZgHIPegRePAtA/xw== + dependencies: + bn.js "^4.4.0" + brorand "^1.0.1" + hash.js "^1.0.0" + hmac-drbg "^1.0.0" + inherits "^2.0.1" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.0" + +"emoji-regex@>=6.0.0 <=6.1.1": + version "6.1.1" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-6.1.1.tgz#c6cd0ec1b0642e2a3c67a1137efc5e796da4f88e" + integrity sha1-xs0OwbBkLio8Z6ETfvxeeW2k+I4= + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emojis-list@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/emojis-list/-/emojis-list-2.1.0.tgz#4daa4d9db00f9819880c79fa457ae5b09a1fd389" + integrity sha1-TapNnbAPmBmIDHn6RXrlsJof04k= + +encodeurl@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" + integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= + +end-of-stream@^1.0.0, end-of-stream@^1.1.0: + version "1.4.4" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" + integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== + dependencies: + once "^1.4.0" + +enhanced-resolve@^4.1.0: + version "4.1.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-4.1.1.tgz#2937e2b8066cd0fe7ce0990a98f0d71a35189f66" + integrity sha512-98p2zE+rL7/g/DzMHMTF4zZlCgeVdJ7yr6xzEpJRYwFYrGi9ANdn5DnJURg6RpBkyk60XYDnWIv51VfIhfNGuA== + dependencies: + graceful-fs "^4.1.2" + memory-fs "^0.5.0" + tapable "^1.0.0" + +entities@^1.1.1, entities@~1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/entities/-/entities-1.1.2.tgz#bdfa735299664dfafd34529ed4f8522a275fea56" + integrity sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w== + +entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/entities/-/entities-2.0.0.tgz#68d6084cab1b079767540d80e56a39b423e4abf4" + integrity sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw== + +envify@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/envify/-/envify-4.1.0.tgz#f39ad3db9d6801b4e6b478b61028d3f0b6819f7e" + integrity sha512-IKRVVoAYr4pIx4yIWNsz9mOsboxlNXiu7TNBnem/K/uTHdkyzXWDzHCK7UTolqBbgaBz0tQHsD3YNls0uIIjiw== + dependencies: + esprima "^4.0.0" + through "~2.3.4" + +errno@^0.1.3, errno@~0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/errno/-/errno-0.1.7.tgz#4684d71779ad39af177e3f007996f7c67c852618" + integrity sha512-MfrRBDWzIWifgq6tJj60gkAwtLNb6sQPlcFrSOflcP1aFmmruKQ2wRnze/8V6kgyz7H3FF8Npzv78mZ7XLLflg== + dependencies: + prr "~1.0.1" + +error-ex@^1.3.1: + version "1.3.2" + resolved "https://registry.yarnpkg.com/error-ex/-/error-ex-1.3.2.tgz#b4ac40648107fdcdcfae242f428bea8a14d4f1bf" + integrity sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g== + dependencies: + is-arrayish "^0.2.1" + +es-abstract@^1.17.0-next.1, es-abstract@^1.17.2: + version "1.17.4" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.17.4.tgz#e3aedf19706b20e7c2594c35fc0d57605a79e184" + integrity sha512-Ae3um/gb8F0mui/jPL+QiqmglkUsaQf7FwBEHYIFkztkneosu9imhqHpBzQ3h1vit8t5iQ74t6PEVvphBZiuiQ== + dependencies: + es-to-primitive "^1.2.1" + function-bind "^1.1.1" + has "^1.0.3" + has-symbols "^1.0.1" + is-callable "^1.1.5" + is-regex "^1.0.5" + object-inspect "^1.7.0" + object-keys "^1.1.1" + object.assign "^4.1.0" + string.prototype.trimleft "^2.1.1" + string.prototype.trimright "^2.1.1" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +es6-promise@^4.1.0: + version "4.2.8" + resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-4.2.8.tgz#4eb21594c972bc40553d276e510539143db53e0a" + integrity sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w== + +escape-html@^1.0.3, escape-html@~1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" + integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= + +escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= + +escape-string-regexp@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344" + integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w== + +eslint-scope@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" + integrity sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg== + dependencies: + esrecurse "^4.1.0" + estraverse "^4.1.1" + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +esrecurse@^4.1.0: + version "4.2.1" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.2.1.tgz#007a3b9fdbc2b3bb87e4879ea19c92fdbd3942cf" + integrity sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ== + dependencies: + estraverse "^4.1.0" + +estraverse@^4.1.0, estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +esutils@^2.0.0, esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +etag@~1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" + integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= + +eval@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/eval/-/eval-0.1.4.tgz#e05dbe0dab4b9330215cbb7bf4886eb24bd58700" + integrity sha512-npGsebJejyjMRnLdFu+T/97dnigqIU0Ov3IGrZ8ygd1v7RL1vGkEKtvyWZobqUH1AQgKlg0Yqqe2BtMA9/QZLw== + dependencies: + require-like ">= 0.1.1" + +eventemitter3@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.0.tgz#d65176163887ee59f386d64c82610b696a4a74eb" + integrity sha512-qerSRB0p+UDEssxTtm6EDKcE7W4OaoisfIMl4CngyEhjpYglocpNg6UEqCvemdGhosAsg4sO2dXJOdyBifPGCg== + +events@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/events/-/events-1.1.1.tgz#9ebdb7635ad099c70dcc4c2a1f5004288e8bd924" + integrity sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ= + +events@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/events/-/events-3.1.0.tgz#84279af1b34cb75aa88bf5ff291f6d0bd9b31a59" + integrity sha512-Rv+u8MLHNOdMjTAFeT3nCjHn2aGlx435FP/sDHNaRhDEMwyI/aB22Kj2qIN8R0cw3z28psEQLYwxVKLsKrMgWg== + +eventsource@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/eventsource/-/eventsource-1.0.7.tgz#8fbc72c93fcd34088090bc0a4e64f4b5cee6d8d0" + integrity sha512-4Ln17+vVT0k8aWq+t/bF5arcS3EpT9gYtW66EPacdj/mAFevznsnyoHLPy2BA8gbIQeIHoPsvwmfBftfcG//BQ== + dependencies: + original "^1.0.0" + +evp_bytestokey@^1.0.0, evp_bytestokey@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz#7fcbdb198dc71959432efe13842684e0525acb02" + integrity sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA== + dependencies: + md5.js "^1.3.4" + safe-buffer "^5.1.1" + +execa@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-1.0.0.tgz#c6236a5bb4df6d6f15e88e7f017798216749ddd8" + integrity sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA== + dependencies: + cross-spawn "^6.0.0" + get-stream "^4.0.0" + is-stream "^1.1.0" + npm-run-path "^2.0.0" + p-finally "^1.0.0" + signal-exit "^3.0.0" + strip-eof "^1.0.0" + +execa@^3.4.0: + version "3.4.0" + resolved "https://registry.yarnpkg.com/execa/-/execa-3.4.0.tgz#c08ed4550ef65d858fac269ffc8572446f37eb89" + integrity sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g== + dependencies: + cross-spawn "^7.0.0" + get-stream "^5.0.0" + human-signals "^1.1.1" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.0" + onetime "^5.1.0" + p-finally "^2.0.0" + signal-exit "^3.0.2" + strip-final-newline "^2.0.0" + +expand-brackets@^2.1.4: + version "2.1.4" + resolved "https://registry.yarnpkg.com/expand-brackets/-/expand-brackets-2.1.4.tgz#b77735e315ce30f6b6eff0f83b04151a22449622" + integrity sha1-t3c14xXOMPa27/D4OwQVGiJEliI= + dependencies: + debug "^2.3.3" + define-property "^0.2.5" + extend-shallow "^2.0.1" + posix-character-classes "^0.1.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +express@^4.16.3, express@^4.17.1: + version "4.17.1" + resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" + integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== + dependencies: + accepts "~1.3.7" + array-flatten "1.1.1" + body-parser "1.19.0" + content-disposition "0.5.3" + content-type "~1.0.4" + cookie "0.4.0" + cookie-signature "1.0.6" + debug "2.6.9" + depd "~1.1.2" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + finalhandler "~1.1.2" + fresh "0.5.2" + merge-descriptors "1.0.1" + methods "~1.1.2" + on-finished "~2.3.0" + parseurl "~1.3.3" + path-to-regexp "0.1.7" + proxy-addr "~2.0.5" + qs "6.7.0" + range-parser "~1.2.1" + safe-buffer "5.1.2" + send "0.17.1" + serve-static "1.14.1" + setprototypeof "1.1.1" + statuses "~1.5.0" + type-is "~1.6.18" + utils-merge "1.0.1" + vary "~1.1.2" + +extend-shallow@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-2.0.1.tgz#51af7d614ad9a9f610ea1bafbb989d6b1c56890f" + integrity sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= + dependencies: + is-extendable "^0.1.0" + +extend-shallow@^3.0.0, extend-shallow@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend-shallow/-/extend-shallow-3.0.2.tgz#26a71aaf073b39fb2127172746131c2704028db8" + integrity sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= + dependencies: + assign-symbols "^1.0.0" + is-extendable "^1.0.1" + +extend@^3.0.0, extend@~3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" + integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== + +external-editor@^3.0.3: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +extglob@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/extglob/-/extglob-2.0.4.tgz#ad00fe4dc612a9232e8718711dc5cb5ab0285543" + integrity sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw== + dependencies: + array-unique "^0.3.2" + define-property "^1.0.0" + expand-brackets "^2.1.4" + extend-shallow "^2.0.1" + fragment-cache "^0.2.1" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +extsprintf@1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" + integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= + +extsprintf@^1.2.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" + integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= + +fast-deep-equal@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" + integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== + +fast-glob@^2.0.2: + version "2.2.7" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-2.2.7.tgz#6953857c3afa475fff92ee6015d52da70a4cd39d" + integrity sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw== + dependencies: + "@mrmlnc/readdir-enhanced" "^2.2.1" + "@nodelib/fs.stat" "^1.1.2" + glob-parent "^3.1.0" + is-glob "^4.0.0" + merge2 "^1.2.3" + micromatch "^3.1.10" + +fast-glob@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.1.1.tgz#87ee30e9e9f3eb40d6f254a7997655da753d7c82" + integrity sha512-nTCREpBY8w8r+boyFYAx21iL6faSsQynliPHM4Uf56SbkyohCNxpVPEH9xrF5TXKy+IsjkPUHDKiUkzBVRXn9g== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.0" + merge2 "^1.3.0" + micromatch "^4.0.2" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fastq@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.6.0.tgz#4ec8a38f4ac25f21492673adb7eae9cfef47d1c2" + integrity sha512-jmxqQ3Z/nXoeyDmWAzF9kH1aGZSis6e/SbfPmJpUnyZ0ogr6iscHQaml4wsEepEWSdtmpy+eVXmCRIMpxaXqOA== + dependencies: + reusify "^1.0.0" + +faye-websocket@^0.10.0: + version "0.10.0" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.10.0.tgz#4e492f8d04dfb6f89003507f6edbf2d501e7c6f4" + integrity sha1-TkkvjQTftviQA1B/btvy1QHnxvQ= + dependencies: + websocket-driver ">=0.5.1" + +faye-websocket@~0.11.1: + version "0.11.3" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.3.tgz#5c0e9a8968e8912c286639fde977a8b209f2508e" + integrity sha512-D2y4bovYpzziGgbHYtGCMjlJM36vAl/y+xUyn1C+FVx8szd1E+86KwVw6XvYSzOP8iMpm1X0I4xJD+QtUb36OA== + dependencies: + websocket-driver ">=0.5.1" + +feed@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/feed/-/feed-4.1.0.tgz#58f1c9cc2b44715d14ac59234e1bf20c5d757aa7" + integrity sha512-dAXWXM8QMxZ1DRnAxDmy1MaWZFlh1Ku7TU3onbXgHrVJynsxkNGPUed1AxszVW8AXo43xExronVkIqK+ACsoBA== + dependencies: + xml-js "^1.6.11" + +figgy-pudding@^3.5.1: + version "3.5.1" + resolved "https://registry.yarnpkg.com/figgy-pudding/-/figgy-pudding-3.5.1.tgz#862470112901c727a0e495a80744bd5baa1d6790" + integrity sha512-vNKxJHTEKNThjfrdJwHc7brvM6eVevuO5nTj6ez8ZQ1qbXTvGthucRF7S4vf2cr71QVnT70V34v0S1DyQsti0w== + +figures@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-2.0.0.tgz#3ab1a2d2a62c8bfb431a0c94cb797a2fce27c962" + integrity sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI= + dependencies: + escape-string-regexp "^1.0.5" + +figures@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/figures/-/figures-3.1.0.tgz#4b198dd07d8d71530642864af2d45dd9e459c4ec" + integrity sha512-ravh8VRXqHuMvZt/d8GblBeqDMkdJMBdv/2KntFH+ra5MXkO7nxNKpzQ3n6QD/2da1kH0aWmNISdvhM7gl2gVg== + dependencies: + escape-string-regexp "^1.0.5" + +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +filesize@3.6.1, filesize@^3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-3.6.1.tgz#090bb3ee01b6f801a8a8be99d31710b3422bb317" + integrity sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg== + +fill-range@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7" + integrity sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= + dependencies: + extend-shallow "^2.0.1" + is-number "^3.0.0" + repeat-string "^1.6.1" + to-regex-range "^2.1.0" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +finalhandler@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" + integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== + dependencies: + debug "2.6.9" + encodeurl "~1.0.2" + escape-html "~1.0.3" + on-finished "~2.3.0" + parseurl "~1.3.3" + statuses "~1.5.0" + unpipe "~1.0.0" + +find-cache-dir@^2.0.0, find-cache-dir@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-2.1.0.tgz#8d0f94cd13fe43c6c7c261a0d86115ca918c05f7" + integrity sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ== + dependencies: + commondir "^1.0.1" + make-dir "^2.0.0" + pkg-dir "^3.0.0" + +find-cache-dir@^3.0.0, find-cache-dir@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.2.0.tgz#e7fe44c1abc1299f516146e563108fd1006c1874" + integrity sha512-1JKclkYYsf1q9WIJKLZa9S9muC+08RIjzAlLrK4QcYLJMS6mk9yombQ9qf+zJ7H9LS800k0s44L4sDq9VYzqyg== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.0" + pkg-dir "^4.1.0" + +find-up@3.0.0, find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +find-up@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7" + integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c= + dependencies: + locate-path "^2.0.0" + +find-up@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +flatten@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/flatten/-/flatten-1.0.3.tgz#c1283ac9f27b368abc1e36d1ff7b04501a30356b" + integrity sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg== + +flush-write-stream@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/flush-write-stream/-/flush-write-stream-1.1.1.tgz#8dd7d873a1babc207d94ead0c2e0e44276ebf2e8" + integrity sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w== + dependencies: + inherits "^2.0.3" + readable-stream "^2.3.6" + +follow-redirects@^1.0.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.10.0.tgz#01f5263aee921c6a54fb91667f08f4155ce169eb" + integrity sha512-4eyLK6s6lH32nOvLLwlIOnr9zrL8Sm+OvW4pVTJNoXeGzYIkHVf+pADQi+OJ0E67hiuSLezPVPyBcIZO50TmmQ== + dependencies: + debug "^3.0.0" + +for-in@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80" + integrity sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= + +foreach@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/foreach/-/foreach-2.0.5.tgz#0bee005018aeb260d0a3af3ae658dd0136ec1b99" + integrity sha1-C+4AUBiusmDQo6865ljdATbsG5k= + +forever-agent@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" + integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= + +fork-ts-checker-webpack-plugin@1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-1.5.0.tgz#ce1d77190b44d81a761b10b6284a373795e41f0c" + integrity sha512-zEhg7Hz+KhZlBhILYpXy+Beu96gwvkROWJiTXOCyOOMMrdBIRPvsBpBqgTI4jfJGrJXcqGwJR8zsBGDmzY0jsA== + dependencies: + babel-code-frame "^6.22.0" + chalk "^2.4.1" + chokidar "^2.0.4" + micromatch "^3.1.10" + minimatch "^3.0.4" + semver "^5.6.0" + tapable "^1.0.0" + worker-rpc "^0.1.0" + +form-data@~2.3.2: + version "2.3.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" + integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.6" + mime-types "^2.1.12" + +forwarded@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" + integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= + +fragment-cache@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/fragment-cache/-/fragment-cache-0.2.1.tgz#4290fad27f13e89be7f33799c6bc5a0abfff0d19" + integrity sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= + dependencies: + map-cache "^0.2.2" + +fresh@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" + integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= + +from2@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/from2/-/from2-2.3.0.tgz#8bfb5502bde4a4d36cfdeea007fcca21d7e382af" + integrity sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= + dependencies: + inherits "^2.0.1" + readable-stream "^2.0.0" + +fs-extra@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-8.1.0.tgz#49d43c45a88cd9677668cb7be1b46efdb8d2e1c0" + integrity sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g== + dependencies: + graceful-fs "^4.2.0" + jsonfile "^4.0.0" + universalify "^0.1.0" + +fs-minipass@^1.2.5: + version "1.2.7" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" + integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== + dependencies: + minipass "^2.6.0" + +fs-minipass@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-2.1.0.tgz#7f5036fdbf12c63c169190cbe4199c852271f9fb" + integrity sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg== + dependencies: + minipass "^3.0.0" + +fs-write-stream-atomic@^1.0.8: + version "1.0.10" + resolved "https://registry.yarnpkg.com/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz#b47df53493ef911df75731e70a9ded0189db40c9" + integrity sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= + dependencies: + graceful-fs "^4.1.2" + iferr "^0.1.5" + imurmurhash "^0.1.4" + readable-stream "1 || 2" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@^1.2.7: + version "1.2.11" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-1.2.11.tgz#67bf57f4758f02ede88fb2a1712fef4d15358be3" + integrity sha512-+ux3lx6peh0BpvY0JebGyZoiR4D+oYzdPZMKJwkZ+sFkNJzpL7tXc/wehS49gUAxg3tmMHPHZkA8JU2rhhgDHw== + dependencies: + bindings "^1.5.0" + nan "^2.12.1" + +fsevents@~2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.1.2.tgz#4c0a1fb34bc68e543b4b82a9ec392bfbda840805" + integrity sha512-R4wDiBwZ0KzpgOWetKDug1FZcYhqYnUYKtfZYt4mD5SBz76q0KR4Q9o7GIPamsVPGmW3EYPPJ0dOOjvx32ldZA== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +gauge@~2.7.3: + version "2.7.4" + resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" + integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= + dependencies: + aproba "^1.0.3" + console-control-strings "^1.0.0" + has-unicode "^2.0.0" + object-assign "^4.1.0" + signal-exit "^3.0.0" + string-width "^1.0.1" + strip-ansi "^3.0.1" + wide-align "^1.1.0" + +gensync@^1.0.0-beta.1: + version "1.0.0-beta.1" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.1.tgz#58f4361ff987e5ff6e1e7a210827aa371eaac269" + integrity sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg== + +get-caller-file@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" + integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== + +get-own-enumerable-property-symbols@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" + integrity sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g== + +get-stream@^4.0.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-4.1.0.tgz#c1b255575f3dc21d59bfc79cd3d2b46b1c3a54b5" + integrity sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w== + dependencies: + pump "^3.0.0" + +get-stream@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-5.1.0.tgz#01203cdc92597f9b909067c3e656cc1f4d3c4dc9" + integrity sha512-EXr1FOzrzTfGeL0gQdeFEvOMm2mzMOglyiOXSTpPC+iAjAKftbr3jpCMWynogwYnM+eSj9sHGc6wjIcDvYiygw== + dependencies: + pump "^3.0.0" + +get-value@^2.0.3, get-value@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28" + integrity sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= + +getpass@^0.1.1: + version "0.1.7" + resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" + integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= + dependencies: + assert-plus "^1.0.0" + +github-slugger@^1.0.0, github-slugger@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/github-slugger/-/github-slugger-1.2.1.tgz#47e904e70bf2dccd0014748142d31126cfd49508" + integrity sha512-SsZUjg/P03KPzQBt7OxJPasGw6NRO5uOgiZ5RGXVud5iSIZ0eNZeNp5rTwCxtavrRUa/A77j8mePVc5lEvk0KQ== + dependencies: + emoji-regex ">=6.0.0 <=6.1.1" + +glob-parent@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-3.1.0.tgz#9e6af6299d8d3bd2bd40430832bd113df906c5ae" + integrity sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= + dependencies: + is-glob "^3.1.0" + path-dirname "^1.0.0" + +glob-parent@^5.1.0, glob-parent@~5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.0.tgz#5f4c1d1e748d30cd73ad2944b3577a81b081e8c2" + integrity sha512-qjtRgnIVmOfnKUE3NJAQEdk+lKrxfw8t5ke7SXtfMTHcjsBfOfWXCQfdb30zfDoZQ2IRSIiidmjtbHZPZ++Ihw== + dependencies: + is-glob "^4.0.1" + +glob-to-regexp@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz#8c5a1494d2066c570cc3bfe4496175acc4d502ab" + integrity sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= + +glob@^7.0.0, glob@^7.0.3, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4: + version "7.1.6" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +global-modules@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/global-modules/-/global-modules-2.0.0.tgz#997605ad2345f27f51539bea26574421215c7780" + integrity sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A== + dependencies: + global-prefix "^3.0.0" + +global-prefix@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/global-prefix/-/global-prefix-3.0.0.tgz#fc85f73064df69f50421f47f883fe5b913ba9b97" + integrity sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg== + dependencies: + ini "^1.3.5" + kind-of "^6.0.2" + which "^1.3.1" + +global@^4.3.2: + version "4.4.0" + resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406" + integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w== + dependencies: + min-document "^2.19.0" + process "^0.11.10" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globby@8.0.2: + version "8.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-8.0.2.tgz#5697619ccd95c5275dbb2d6faa42087c1a941d8d" + integrity sha512-yTzMmKygLp8RUpG1Ymu2VXPSJQZjNAZPD4ywgYEaG7e4tBJeUQBO8OpXrf1RCNcEs5alsoJYPAMiIHP0cmeC7w== + dependencies: + array-union "^1.0.1" + dir-glob "2.0.0" + fast-glob "^2.0.2" + glob "^7.1.2" + ignore "^3.3.5" + pify "^3.0.0" + slash "^1.0.0" + +globby@^10.0.1: + version "10.0.2" + resolved "https://registry.yarnpkg.com/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" + integrity sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + +globby@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c" + integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= + dependencies: + array-union "^1.0.1" + glob "^7.0.3" + object-assign "^4.0.1" + pify "^2.0.0" + pinkie-promise "^2.0.0" + +globby@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/globby/-/globby-7.1.1.tgz#fb2ccff9401f8600945dfada97440cca972b8680" + integrity sha1-+yzP+UAfhgCUXfral0QMypcrhoA= + dependencies: + array-union "^1.0.1" + dir-glob "^2.0.0" + glob "^7.1.2" + ignore "^3.3.5" + pify "^3.0.0" + slash "^1.0.0" + +good-listener@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/good-listener/-/good-listener-1.2.2.tgz#d53b30cdf9313dffb7dc9a0d477096aa6d145c50" + integrity sha1-1TswzfkxPf+33JoNR3CWqm0UXFA= + dependencies: + delegate "^3.1.2" + +graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.2: + version "4.2.3" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" + integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== + +gray-matter@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/gray-matter/-/gray-matter-4.0.2.tgz#9aa379e3acaf421193fce7d2a28cebd4518ac454" + integrity sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw== + dependencies: + js-yaml "^3.11.0" + kind-of "^6.0.2" + section-matter "^1.0.0" + strip-bom-string "^1.0.0" + +gud@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" + integrity sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw== + +gzip-size@5.1.1, gzip-size@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-5.1.1.tgz#cb9bee692f87c0612b232840a873904e4c135274" + integrity sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA== + dependencies: + duplexer "^0.1.1" + pify "^4.0.1" + +handle-thing@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/handle-thing/-/handle-thing-2.0.0.tgz#0e039695ff50c93fc288557d696f3c1dc6776754" + integrity sha512-d4sze1JNC454Wdo2fkuyzCr6aHcbL6PGGuFAz0Li/NcOm1tCHGnWDRmJP85dh9IhQErTc2svWFEX5xHIOo//kQ== + +har-schema@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" + integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= + +har-validator@~5.1.3: + version "5.1.3" + resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" + integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== + dependencies: + ajv "^6.5.5" + har-schema "^2.0.0" + +has-ansi@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/has-ansi/-/has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + integrity sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE= + dependencies: + ansi-regex "^2.0.0" + +has-flag@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" + integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-symbols@^1.0.0, has-symbols@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" + integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== + +has-unicode@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" + integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= + +has-value@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-0.3.1.tgz#7b1f58bada62ca827ec0a2078025654845995e1f" + integrity sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= + dependencies: + get-value "^2.0.3" + has-values "^0.1.4" + isobject "^2.0.0" + +has-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-value/-/has-value-1.0.0.tgz#18b281da585b1c5c51def24c930ed29a0be6b177" + integrity sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= + dependencies: + get-value "^2.0.6" + has-values "^1.0.0" + isobject "^3.0.0" + +has-values@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-0.1.4.tgz#6d61de95d91dfca9b9a02089ad384bff8f62b771" + integrity sha1-bWHeldkd/Km5oCCJrThL/49it3E= + +has-values@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-values/-/has-values-1.0.0.tgz#95b0b63fec2146619a6fe57fe75628d5a39efe4f" + integrity sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= + dependencies: + is-number "^3.0.0" + kind-of "^4.0.0" + +has@^1.0.0, has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hash-base@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/hash-base/-/hash-base-3.0.4.tgz#5fc8686847ecd73499403319a6b0a3f3f6ae4918" + integrity sha1-X8hoaEfs1zSZQDMZprCj8/auSRg= + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +hash.js@^1.0.0, hash.js@^1.0.3: + version "1.1.7" + resolved "https://registry.yarnpkg.com/hash.js/-/hash.js-1.1.7.tgz#0babca538e8d4ee4a0f8988d68866537a003cf42" + integrity sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA== + dependencies: + inherits "^2.0.3" + minimalistic-assert "^1.0.1" + +hast-to-hyperscript@^7.0.0: + version "7.0.4" + resolved "https://registry.yarnpkg.com/hast-to-hyperscript/-/hast-to-hyperscript-7.0.4.tgz#7c4c037d9a8ea19b0a3fdb676a26448ad922353d" + integrity sha512-vmwriQ2H0RPS9ho4Kkbf3n3lY436QKLq6VaGA1pzBh36hBi3tm1DO9bR+kaJIbpT10UqaANDkMjxvjVfr+cnOA== + dependencies: + comma-separated-tokens "^1.0.0" + property-information "^5.3.0" + space-separated-tokens "^1.0.0" + style-to-object "^0.2.1" + unist-util-is "^3.0.0" + web-namespaces "^1.1.2" + +hast-util-from-parse5@^5.0.0: + version "5.0.2" + resolved "https://registry.yarnpkg.com/hast-util-from-parse5/-/hast-util-from-parse5-5.0.2.tgz#afeadc6aab41e6acfe038645bbefd4005c56a475" + integrity sha512-YXFjoRS7ES7PEoLx6uihtSfKTO1s3z/tzGiV5cVpsUiihduogFXubNRCzTIW3yOOGO1nws9CxPq4MbwD39Uo+w== + dependencies: + ccount "^1.0.3" + hastscript "^5.0.0" + property-information "^5.0.0" + web-namespaces "^1.1.2" + xtend "^4.0.1" + +hast-util-parse-selector@^2.0.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.3.tgz#57edd449103900c7f63fd9e6f694ffd7e4634719" + integrity sha512-nxbeqjQNxsvo/uYYAw9kij6td05YVUlf1qti09rVfbWSLT5H6wo3c+USIwX6nzXWk5kFZzXnEqO82856r0aM2Q== + +hast-util-raw@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/hast-util-raw/-/hast-util-raw-5.0.1.tgz#b39539cf4b9f7ccdc131f72a583502a7911b99ee" + integrity sha512-iHo7G6BjRc/GU1Yun5CIEXjil0wVnIbz11C6k0JdDichSDMtYi2+NNtk6YN7EOP0JfPstX30d3pRLfaJv5CkdA== + dependencies: + hast-util-from-parse5 "^5.0.0" + hast-util-to-parse5 "^5.0.0" + html-void-elements "^1.0.1" + parse5 "^5.0.0" + unist-util-position "^3.0.0" + web-namespaces "^1.0.0" + xtend "^4.0.1" + zwitch "^1.0.0" + +hast-util-to-parse5@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/hast-util-to-parse5/-/hast-util-to-parse5-5.1.1.tgz#cabf2dbe9ed988a5128fc708457b37cdf535a2e8" + integrity sha512-ivCeAd5FCXr7bapJIVsWMnx/EmbjkkW2TU2hd1prq+jGwiaUoK+FcpjyPNwsC5ogzCwWO669tOqIovGeLc/ntg== + dependencies: + hast-to-hyperscript "^7.0.0" + property-information "^5.0.0" + web-namespaces "^1.0.0" + xtend "^4.0.1" + zwitch "^1.0.0" + +hastscript@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-5.1.1.tgz#71726ee1e97220575d1f29a8e937387d99d48275" + integrity sha512-xHo1Hkcqd0LlWNuDL3/BxwhgAGp3d7uEvCMgCTrBY+zsOooPPH+8KAvW8PCgl+GB8H3H44nfSaF0A4BQ+4xlYg== + dependencies: + comma-separated-tokens "^1.0.0" + hast-util-parse-selector "^2.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +hex-color-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/hex-color-regex/-/hex-color-regex-1.1.0.tgz#4c06fccb4602fe2602b3c93df82d7e7dbf1a8a8e" + integrity sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ== + +history@^4.9.0: + version "4.10.1" + resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" + integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew== + dependencies: + "@babel/runtime" "^7.1.2" + loose-envify "^1.2.0" + resolve-pathname "^3.0.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + value-equal "^1.0.1" + +hmac-drbg@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/hmac-drbg/-/hmac-drbg-1.0.1.tgz#d2745701025a6c775a6c545793ed502fc0c649a1" + integrity sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= + dependencies: + hash.js "^1.0.3" + minimalistic-assert "^1.0.0" + minimalistic-crypto-utils "^1.0.1" + +hogan.js@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/hogan.js/-/hogan.js-3.0.2.tgz#4cd9e1abd4294146e7679e41d7898732b02c7bfd" + integrity sha1-TNnhq9QpQUbnZ55B14mHMrAse/0= + dependencies: + mkdirp "0.3.0" + nopt "1.0.10" + +hoist-non-react-statics@^3.1.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + +hoopy@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/hoopy/-/hoopy-0.1.4.tgz#609207d661100033a9a9402ad3dea677381c1b1d" + integrity sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ== + +hpack.js@^2.1.6: + version "2.1.6" + resolved "https://registry.yarnpkg.com/hpack.js/-/hpack.js-2.1.6.tgz#87774c0949e513f42e84575b3c45681fade2a0b2" + integrity sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= + dependencies: + inherits "^2.0.1" + obuf "^1.0.0" + readable-stream "^2.0.1" + wbuf "^1.1.0" + +hsl-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsl-regex/-/hsl-regex-1.0.0.tgz#d49330c789ed819e276a4c0d272dffa30b18fe6e" + integrity sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= + +hsla-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/hsla-regex/-/hsla-regex-1.0.0.tgz#c1ce7a3168c8c6614033a4b5f7877f3b225f9c38" + integrity sha1-wc56MWjIxmFAM6S194d/OyJfnDg= + +html-comment-regex@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/html-comment-regex/-/html-comment-regex-1.1.2.tgz#97d4688aeb5c81886a364faa0cad1dda14d433a7" + integrity sha512-P+M65QY2JQ5Y0G9KKdlDpo0zK+/OHptU5AaBwUfAIDJZk1MYf32Frm84EcOytfJE0t5JvkAnKlmjsXDnWzCJmQ== + +html-entities@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-1.2.1.tgz#0df29351f0721163515dfb9e5543e5f6eed5162f" + integrity sha1-DfKTUfByEWNRXfueVUPl9u7VFi8= + +html-minifier-terser@^5.0.1, html-minifier-terser@^5.0.2: + version "5.0.3" + resolved "https://registry.yarnpkg.com/html-minifier-terser/-/html-minifier-terser-5.0.3.tgz#b33549b57be7f0357be0d0b892995aaed1ed90f8" + integrity sha512-It4No3H1V3Dhd/O0MePFdo0oX/M6u6YZTMw4My/010mT6vxdbqge7+0RoxGAmeSbKok6gjYZoP0p4rpZ2+J2yw== + dependencies: + camel-case "^3.0.0" + clean-css "^4.2.1" + commander "^4.0.0" + he "^1.2.0" + param-case "^2.1.1" + relateurl "^0.2.7" + terser "^4.3.9" + +html-tags@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" + integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== + +html-void-elements@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/html-void-elements/-/html-void-elements-1.0.5.tgz#ce9159494e86d95e45795b166c2021c2cfca4483" + integrity sha512-uE/TxKuyNIcx44cIWnjr/rfIATDH7ZaOMmstu0CwhFG1Dunhlp4OC6/NMbhiwoq5BpW0ubi303qnEk/PZj614w== + +html-webpack-plugin@^4.0.0-beta.11: + version "4.0.0-beta.11" + resolved "https://registry.yarnpkg.com/html-webpack-plugin/-/html-webpack-plugin-4.0.0-beta.11.tgz#3059a69144b5aecef97708196ca32f9e68677715" + integrity sha512-4Xzepf0qWxf8CGg7/WQM5qBB2Lc/NFI7MhU59eUDTkuQp3skZczH4UA1d6oQyDEIoMDgERVhRyTdtUPZ5s5HBg== + dependencies: + html-minifier-terser "^5.0.1" + loader-utils "^1.2.3" + lodash "^4.17.15" + pretty-error "^2.1.1" + tapable "^1.1.3" + util.promisify "1.0.0" + +htmlparser2@^3.3.0, htmlparser2@^3.9.1: + version "3.10.1" + resolved "https://registry.yarnpkg.com/htmlparser2/-/htmlparser2-3.10.1.tgz#bd679dc3f59897b6a34bb10749c855bb53a9392f" + integrity sha512-IgieNijUMbkDovyoKObU1DUhm1iwNYE/fuifEoEHfd1oZKZDaONBSkal7Y01shxsM49R4XaMdGez3WnF9UfiCQ== + dependencies: + domelementtype "^1.3.1" + domhandler "^2.3.0" + domutils "^1.5.1" + entities "^1.1.1" + inherits "^2.0.1" + readable-stream "^3.1.1" + +http-deceiver@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/http-deceiver/-/http-deceiver-1.2.7.tgz#fa7168944ab9a519d337cb0bec7284dc3e723d87" + integrity sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= + +http-errors@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" + integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +http-errors@~1.6.2: + version "1.6.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.6.3.tgz#8b55680bb4be283a0b5bf4ea2e38580be1d9320d" + integrity sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= + dependencies: + depd "~1.1.2" + inherits "2.0.3" + setprototypeof "1.1.0" + statuses ">= 1.4.0 < 2" + +http-errors@~1.7.2: + version "1.7.3" + resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" + integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== + dependencies: + depd "~1.1.2" + inherits "2.0.4" + setprototypeof "1.1.1" + statuses ">= 1.5.0 < 2" + toidentifier "1.0.0" + +"http-parser-js@>=0.4.0 <0.4.11": + version "0.4.10" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.4.10.tgz#92c9c1374c35085f75db359ec56cc257cbb93fa4" + integrity sha1-ksnBN0w1CF912zWexWzCV8u5P6Q= + +http-proxy-middleware@0.19.1: + version "0.19.1" + resolved "https://registry.yarnpkg.com/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz#183c7dc4aa1479150306498c210cdaf96080a43a" + integrity sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q== + dependencies: + http-proxy "^1.17.0" + is-glob "^4.0.0" + lodash "^4.17.11" + micromatch "^3.1.10" + +http-proxy@^1.17.0: + version "1.18.0" + resolved "https://registry.yarnpkg.com/http-proxy/-/http-proxy-1.18.0.tgz#dbe55f63e75a347db7f3d99974f2692a314a6a3a" + integrity sha512-84I2iJM/n1d4Hdgc6y2+qY5mDaz2PUVjlg9znE9byl+q0uC3DeByqBGReQu5tpLK0TAqTIXScRUV+dg7+bUPpQ== + dependencies: + eventemitter3 "^4.0.0" + follow-redirects "^1.0.0" + requires-port "^1.0.0" + +http-signature@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" + integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= + dependencies: + assert-plus "^1.0.0" + jsprim "^1.2.2" + sshpk "^1.7.0" + +https-browserify@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/https-browserify/-/https-browserify-1.0.0.tgz#ec06c10e0a34c0f2faf199f7fd7fc78fffd03c73" + integrity sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= + +human-signals@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-1.1.1.tgz#c5b1cd14f50aeae09ab6c59fe63ba3395fe4dfa3" + integrity sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw== + +iconv-lite@0.4.24, iconv-lite@^0.4.24, iconv-lite@^0.4.4: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +icss-utils@^4.0.0, icss-utils@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/icss-utils/-/icss-utils-4.1.1.tgz#21170b53789ee27447c2f47dd683081403f9a467" + integrity sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA== + dependencies: + postcss "^7.0.14" + +ieee754@^1.1.4: + version "1.1.13" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.1.13.tgz#ec168558e95aa181fd87d37f55c32bbcb6708b84" + integrity sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg== + +iferr@^0.1.5: + version "0.1.5" + resolved "https://registry.yarnpkg.com/iferr/-/iferr-0.1.5.tgz#c60eed69e6d8fdb6b3104a1fcbca1c192dc5b501" + integrity sha1-xg7taebY/bazEEofy8ocGS3FtQE= + +ignore-walk@^3.0.1: + version "3.0.3" + resolved "https://registry.yarnpkg.com/ignore-walk/-/ignore-walk-3.0.3.tgz#017e2447184bfeade7c238e4aefdd1e8f95b1e37" + integrity sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw== + dependencies: + minimatch "^3.0.4" + +ignore@^3.3.5: + version "3.3.10" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-3.3.10.tgz#0a97fb876986e8081c631160f8f9f389157f0043" + integrity sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug== + +ignore@^5.1.1: + version "5.1.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.1.4.tgz#84b7b3dbe64552b6ef0eca99f6743dbec6d97adf" + integrity sha512-MzbUSahkTW1u7JpKKjY7LCARd1fU5W2rLdxlM4kdkayuCwZImjkpluF9CM1aLewYJguPDqewLam18Y6AU69A8A== + +immediate@^3.2.3: + version "3.2.3" + resolved "https://registry.yarnpkg.com/immediate/-/immediate-3.2.3.tgz#d140fa8f614659bd6541233097ddaac25cdd991c" + integrity sha1-0UD6j2FGWb1lQSMwl92qwlzdmRw= + +immer@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/immer/-/immer-1.10.0.tgz#bad67605ba9c810275d91e1c2a47d4582e98286d" + integrity sha512-O3sR1/opvCDGLEVcvrGTMtLac8GJ5IwZC4puPrLuRj3l7ICKvkmA0vGuU9OW8mV9WIBRnaxp5GJh9IEAaNOoYg== + +import-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-cwd/-/import-cwd-2.1.0.tgz#aa6cf36e722761285cb371ec6519f53e2435b0a9" + integrity sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= + dependencies: + import-from "^2.1.0" + +import-fresh@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" + integrity sha1-2BNVwVYS04bGH53dOSLUMEgipUY= + dependencies: + caller-path "^2.0.0" + resolve-from "^3.0.0" + +import-fresh@^3.2.1: + version "3.2.1" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.2.1.tgz#633ff618506e793af5ac91bf48b72677e15cbe66" + integrity sha512-6e1q1cnWP2RXD9/keSkxHScg508CdXqXWgWBaETNhyuBFz+kUZlKboh+ISK+bU++DmbHimVBrOz/zzPe0sZ3sQ== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +import-from@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/import-from/-/import-from-2.1.0.tgz#335db7f2a7affd53aaa471d4b8021dee36b7f3b1" + integrity sha1-M1238qev/VOqpHHUuAId7ja387E= + dependencies: + resolve-from "^3.0.0" + +import-local@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/import-local/-/import-local-2.0.0.tgz#55070be38a5993cf18ef6db7e961f5bee5c5a09d" + integrity sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ== + dependencies: + pkg-dir "^3.0.0" + resolve-cwd "^2.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +indexes-of@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/indexes-of/-/indexes-of-1.0.1.tgz#f30f716c8e2bd346c7b67d3df3915566a7c05607" + integrity sha1-8w9xbI4r00bHtn0985FVZqfAVgc= + +infer-owner@^1.0.3, infer-owner@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/infer-owner/-/infer-owner-1.0.4.tgz#c4cefcaa8e51051c2a40ba2ce8a3d27295af9467" + integrity sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A== + +infima@0.2.0-alpha.3: + version "0.2.0-alpha.3" + resolved "https://registry.yarnpkg.com/infima/-/infima-0.2.0-alpha.3.tgz#86c0bd9ee7a38e921bee0611970f1a7b71d69b32" + integrity sha512-3DusmJsdsaZeLYgcHubVQHqRht/0/evhfGaqQBcBgp/vnc7TEeoLUBREJTHMFdCoZUGDy2UfkNiMAwpUrVhyEg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2, inherits@2.0.4, inherits@^2.0.0, inherits@^2.0.1, inherits@^2.0.3, inherits@~2.0.1, inherits@~2.0.3: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inherits@2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.1.tgz#b17d08d326b4423e568eff719f91b0b1cbdf69f1" + integrity sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= + +inherits@2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= + +ini@^1.3.5, ini@~1.3.0: + version "1.3.5" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.5.tgz#eee25f56db1c9ec6085e0c22778083f596abf927" + integrity sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw== + +inline-style-parser@0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/inline-style-parser/-/inline-style-parser-0.1.1.tgz#ec8a3b429274e9c0a1f1c4ffa9453a7fef72cea1" + integrity sha512-7NXolsK4CAS5+xvdj5OMMbI962hU/wvwoxk+LWR9Ek9bVtyuuYScDN6eS0rUm6TxApFpw7CX1o4uJzcd4AyD3Q== + +inquirer@6.5.0: + version "6.5.0" + resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-6.5.0.tgz#2303317efc9a4ea7ec2e2df6f86569b734accf42" + integrity sha512-scfHejeG/lVZSpvCXpsB4j/wQNPM5JC8kiElOI0OUTwmc1RTpXr4H32/HOlQHcZiYl2z2VElwuCVDRG8vFmbnA== + dependencies: + ansi-escapes "^3.2.0" + chalk "^2.4.2" + cli-cursor "^2.1.0" + cli-width "^2.0.0" + external-editor "^3.0.3" + figures "^2.0.0" + lodash "^4.17.12" + mute-stream "0.0.7" + run-async "^2.2.0" + rxjs "^6.4.0" + string-width "^2.1.0" + strip-ansi "^5.1.0" + through "^2.3.6" + +internal-ip@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/internal-ip/-/internal-ip-4.3.0.tgz#845452baad9d2ca3b69c635a137acb9a0dad0907" + integrity sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg== + dependencies: + default-gateway "^4.2.0" + ipaddr.js "^1.9.0" + +interpret@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.2.0.tgz#d5061a6224be58e8083985f5014d844359576296" + integrity sha512-mT34yGKMNceBQUoVn7iCDKDntA7SC6gycMAWzGx1z/CMCTV7b2AAtXlo3nRyHZ1FelRkQbQjprHSYGwzLtkVbw== + +invariant@^2.2.2, invariant@^2.2.4: + version "2.2.4" + resolved "https://registry.yarnpkg.com/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" + integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== + dependencies: + loose-envify "^1.0.0" + +invert-kv@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/invert-kv/-/invert-kv-2.0.0.tgz#7393f5afa59ec9ff5f67a27620d11c226e3eec02" + integrity sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA== + +ip-regex@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-2.1.0.tgz#fa78bf5d2e6913c911ce9f819ee5146bb6d844e9" + integrity sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= + +ip@^1.1.0, ip@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/ip/-/ip-1.1.5.tgz#bdded70114290828c0a039e72ef25f5aaec4354a" + integrity sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= + +ipaddr.js@1.9.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.0.tgz#37df74e430a0e47550fe54a2defe30d8acd95f65" + integrity sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA== + +ipaddr.js@^1.9.0: + version "1.9.1" + resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" + integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== + +is-absolute-url@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-2.1.0.tgz#50530dfb84fcc9aa7dbe7852e83a37b93b9f2aa6" + integrity sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= + +is-absolute-url@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-absolute-url/-/is-absolute-url-3.0.3.tgz#96c6a22b6a23929b11ea0afb1836c36ad4a5d698" + integrity sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q== + +is-accessor-descriptor@^0.1.6: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz#a9e12cb3ae8d876727eeef3843f8a0897b5c98d6" + integrity sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= + dependencies: + kind-of "^3.0.2" + +is-accessor-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz#169c2f6d3df1f992618072365c9b0ea1f6878656" + integrity sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ== + dependencies: + kind-of "^6.0.0" + +is-alphabetical@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.3.tgz#eb04cc47219a8895d8450ace4715abff2258a1f8" + integrity sha512-eEMa6MKpHFzw38eKm56iNNi6GJ7lf6aLLio7Kr23sJPAECscgRtZvOBYybejWDQ2bM949Y++61PY+udzj5QMLA== + +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + +is-arguments@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-arguments/-/is-arguments-1.0.4.tgz#3faf966c7cba0ff437fb31f6250082fcf0448cf3" + integrity sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA== + +is-arrayish@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.2.1.tgz#77c99840527aa8ecb1a8ba697b80645a7a926a9d" + integrity sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= + +is-arrayish@^0.3.1: + version "0.3.2" + resolved "https://registry.yarnpkg.com/is-arrayish/-/is-arrayish-0.3.2.tgz#4574a2ae56f7ab206896fb431eaeed066fdf8f03" + integrity sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ== + +is-binary-path@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-1.0.1.tgz#75f16642b480f187a711c814161fd3a4a7655898" + integrity sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= + dependencies: + binary-extensions "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-buffer@^1.1.5: + version "1.1.6" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be" + integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w== + +is-buffer@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.4.tgz#3e572f23c8411a5cfd9557c849e3665e0b290623" + integrity sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A== + +is-callable@^1.1.4, is-callable@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.5.tgz#f7e46b596890456db74e7f6e976cb3273d06faab" + integrity sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q== + +is-color-stop@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-color-stop/-/is-color-stop-1.1.0.tgz#cfff471aee4dd5c9e158598fbe12967b5cdad345" + integrity sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= + dependencies: + css-color-names "^0.0.4" + hex-color-regex "^1.1.0" + hsl-regex "^1.0.0" + hsla-regex "^1.0.0" + rgb-regex "^1.0.1" + rgba-regex "^1.0.0" + +is-data-descriptor@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz#0b5ee648388e2c860282e793f1856fec3f301b56" + integrity sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= + dependencies: + kind-of "^3.0.2" + +is-data-descriptor@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz#d84876321d0e7add03990406abbbbd36ba9268c7" + integrity sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ== + dependencies: + kind-of "^6.0.0" + +is-date-object@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.2.tgz#bda736f2cd8fd06d32844e7743bfa7494c3bfd7e" + integrity sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g== + +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + +is-descriptor@^0.1.0: + version "0.1.6" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-0.1.6.tgz#366d8240dde487ca51823b1ab9f07a10a78251ca" + integrity sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg== + dependencies: + is-accessor-descriptor "^0.1.6" + is-data-descriptor "^0.1.4" + kind-of "^5.0.0" + +is-descriptor@^1.0.0, is-descriptor@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-descriptor/-/is-descriptor-1.0.2.tgz#3b159746a66604b04f8c81524ba365c5f14d86ec" + integrity sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg== + dependencies: + is-accessor-descriptor "^1.0.0" + is-data-descriptor "^1.0.0" + kind-of "^6.0.2" + +is-directory@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/is-directory/-/is-directory-0.3.1.tgz#61339b6f2475fc772fd9c9d83f5c8575dc154ae1" + integrity sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= + +is-extendable@^0.1.0, is-extendable@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" + integrity sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= + +is-extendable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-1.0.1.tgz#a7470f9e426733d81bd81e1155264e3a3507cab4" + integrity sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA== + dependencies: + is-plain-object "^2.0.4" + +is-extglob@^2.1.0, is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" + integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= + dependencies: + number-is-nan "^1.0.0" + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-3.1.0.tgz#7ba5ae24217804ac70707b96922567486cc3e84a" + integrity sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= + dependencies: + is-extglob "^2.1.0" + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + +is-number@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-3.0.0.tgz#24fd6201a4782cf50561c810276afc7d12d71195" + integrity sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= + dependencies: + kind-of "^3.0.2" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-obj@^1.0.0, is-obj@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f" + integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8= + +is-path-cwd@^2.0.0, is-path-cwd@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-path-cwd/-/is-path-cwd-2.2.0.tgz#67d43b82664a7b5191fd9119127eb300048a9fdb" + integrity sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ== + +is-path-in-cwd@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz#bfe2dca26c69f397265a4009963602935a053acb" + integrity sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ== + dependencies: + is-path-inside "^2.1.0" + +is-path-inside@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-2.1.0.tgz#7c9810587d659a40d27bcdb4d5616eab059494b2" + integrity sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg== + dependencies: + path-is-inside "^1.0.2" + +is-path-inside@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" + integrity sha512-/2UGPSgmtqwo1ktx8NDHjuPwZWmHhO+gj0f93EkhLB5RgW9RZevWYYlIkS6zePc6U2WpOdQYIwHe9YC4DWEBVg== + +is-plain-obj@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" + integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= + +is-plain-obj@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-plain-object@^2.0.3, is-plain-object@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" + integrity sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og== + dependencies: + isobject "^3.0.1" + +is-promise@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.1.0.tgz#79a2a9ece7f096e80f36d2b2f3bc16c1ff4bf3fa" + integrity sha1-eaKp7OfwlugPNtKy87wWwf9L8/o= + +is-regex@^1.0.4, is-regex@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.5.tgz#39d589a358bf18967f726967120b8fc1aed74eae" + integrity sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ== + dependencies: + has "^1.0.3" + +is-regexp@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-regexp/-/is-regexp-1.0.0.tgz#fd2d883545c46bac5a633e7b9a09e87fa2cb5069" + integrity sha1-/S2INUXEa6xaYz57mgnof6LLUGk= + +is-resolvable@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-resolvable/-/is-resolvable-1.1.0.tgz#fb18f87ce1feb925169c9a407c19318a3206ed88" + integrity sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg== + +is-root@2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-root/-/is-root-2.1.0.tgz#809e18129cf1129644302a4f8544035d51984a9c" + integrity sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg== + +is-stream@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44" + integrity sha1-EtSj3U5o4Lec6428hBc66A2RykQ= + +is-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.0.tgz#bde9c32680d6fae04129d6ac9d921ce7815f78e3" + integrity sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw== + +is-svg@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-svg/-/is-svg-3.0.0.tgz#9321dbd29c212e5ca99c4fa9794c714bcafa2f75" + integrity sha512-gi4iHK53LR2ujhLVVj+37Ykh9GLqYHX6JOVXbLAucaG/Cqw9xwdFOjDM2qeifLs1sF1npXXFvDu0r5HNgCMrzQ== + dependencies: + html-comment-regex "^1.1.0" + +is-symbol@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.3.tgz#38e1014b9e6329be0de9d24a414fd7441ec61937" + integrity sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ== + dependencies: + has-symbols "^1.0.1" + +is-typedarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= + +is-whitespace-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" + integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +is-word-character@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-word-character/-/is-word-character-1.0.4.tgz#ce0e73216f98599060592f62ff31354ddbeb0230" + integrity sha512-5SMO8RVennx3nZrqtKwCGyyetPE9VDba5ugvKLaD4KopPG5kR4mQ7tNt/r7feL5yt5h3lpuBbIUmCOG2eSzXHA== + +is-wsl@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-1.1.0.tgz#1f16e4aa22b04d1336b66188a66af3c600c3a66d" + integrity sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= + +isarray@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" + integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + +isarray@1.0.0, isarray@^1.0.0, isarray@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" + integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= + +isarray@^2.0.1: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +isobject@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-2.1.0.tgz#f065561096a3f1da2ef46272f815c840d87e0c89" + integrity sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= + dependencies: + isarray "1.0.0" + +isobject@^3.0.0, isobject@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/isobject/-/isobject-3.0.1.tgz#4e431e92b11a9731636aa1f9c8d1ccbcfdab78df" + integrity sha1-TkMekrEalzFjaqH5yNHMvP2reN8= + +isstream@~0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" + integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= + +jest-worker@^25.1.0: + version "25.1.0" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-25.1.0.tgz#75d038bad6fdf58eba0d2ec1835856c497e3907a" + integrity sha512-ZHhHtlxOWSxCoNOKHGbiLzXnl42ga9CxDr27H36Qn+15pQZd3R/F24jrmjDelw9j/iHUIWMWs08/u2QN50HHOg== + dependencies: + merge-stream "^2.0.0" + supports-color "^7.0.0" + +"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-tokens@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + integrity sha1-mGbfOVECEw449/mWvOtlRDIJwls= + +js-yaml@^3.11.0, js-yaml@^3.13.1: + version "3.13.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" + integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +jsbn@~0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" + integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= + +jsesc@^2.5.1: + version "2.5.2" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4" + integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== + +jsesc@~0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d" + integrity sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= + +json-parse-better-errors@^1.0.1, json-parse-better-errors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9" + integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw== + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-schema@0.2.3: + version "0.2.3" + resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" + integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= + +json-stringify-safe@~5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" + integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= + +json3@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/json3/-/json3-3.3.3.tgz#7fc10e375fc5ae42c4705a5cc0aa6f62be305b81" + integrity sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA== + +json5@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.1.tgz#779fb0018604fa854eacbf6252180d83543e3dbe" + integrity sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow== + dependencies: + minimist "^1.2.0" + +json5@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.1.1.tgz#81b6cb04e9ba496f1c7005d07b4368a2638f90b6" + integrity sha512-l+3HXD0GEI3huGq1njuqtzYK8OYJyXMkOLtQ53pjWh89tvWS2h6l+1zMkYWqlb57+SiQodKZyvMEFb2X+KrFhQ== + dependencies: + minimist "^1.2.0" + +jsonfile@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" + integrity sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= + optionalDependencies: + graceful-fs "^4.1.6" + +jsprim@^1.2.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" + integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= + dependencies: + assert-plus "1.0.0" + extsprintf "1.3.0" + json-schema "0.2.3" + verror "1.10.0" + +killable@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/killable/-/killable-1.0.1.tgz#4c8ce441187a061c7474fb87ca08e2a638194892" + integrity sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg== + +kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-3.2.2.tgz#31ea21a734bab9bbb0f32466d893aea51e4a3c64" + integrity sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= + dependencies: + is-buffer "^1.1.5" + +kind-of@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-4.0.0.tgz#20813df3d712928b207378691a45066fae72dd57" + integrity sha1-IIE989cSkosgc3hpGkUGb65y3Vc= + dependencies: + is-buffer "^1.1.5" + +kind-of@^5.0.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-5.1.0.tgz#729c91e2d857b7a419a1f9aa65685c4c33f5845d" + integrity sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw== + +kind-of@^6.0.0, kind-of@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/kind-of/-/kind-of-6.0.3.tgz#07c05034a6c349fa06e24fa35aa76db4580ce4dd" + integrity sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw== + +last-call-webpack-plugin@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/last-call-webpack-plugin/-/last-call-webpack-plugin-3.0.0.tgz#9742df0e10e3cf46e5c0381c2de90d3a7a2d7555" + integrity sha512-7KI2l2GIZa9p2spzPIVZBYyNKkN+e/SQPpnjlTiPhdbDW3F86tdKKELxKpzJ5sgU19wQWsACULZmpTPYHeWO5w== + dependencies: + lodash "^4.17.5" + webpack-sources "^1.1.0" + +lcid@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/lcid/-/lcid-2.0.0.tgz#6ef5d2df60e52f82eb228a4c373e8d1f397253cf" + integrity sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA== + dependencies: + invert-kv "^2.0.0" + +leven@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/leven/-/leven-3.1.0.tgz#77891de834064cccba82ae7842bb6b14a13ed7f2" + integrity sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A== + +levenary@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/levenary/-/levenary-1.1.1.tgz#842a9ee98d2075aa7faeedbe32679e9205f46f77" + integrity sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ== + dependencies: + leven "^3.1.0" + +load-script@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/load-script/-/load-script-1.0.0.tgz#0491939e0bee5643ee494a7e3da3d2bac70c6ca4" + integrity sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ= + +loader-runner@^2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-2.4.0.tgz#ed47066bfe534d7e84c4c7b9998c2a75607d9357" + integrity sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw== + +loader-utils@1.2.3, loader-utils@^1.0.2, loader-utils@^1.1.0, loader-utils@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/loader-utils/-/loader-utils-1.2.3.tgz#1ff5dc6911c9f0a062531a4c04b609406108c2c7" + integrity sha512-fkpz8ejdnEMG3s37wGL07iSBDg99O9D5yflE9RGNH3hRdx9SOwYfnGYdZOUIZitN8E+E2vkq3MUMYMvPYl5ZZA== + dependencies: + big.js "^5.2.2" + emojis-list "^2.0.0" + json5 "^1.0.1" + +locate-path@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e" + integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4= + dependencies: + p-locate "^2.0.0" + path-exists "^3.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +lodash._reinterpolate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" + integrity sha1-DM8tiRZq8Ds2Y8eWU4t1rG4RTZ0= + +lodash.assignin@^4.0.9: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.assignin/-/lodash.assignin-4.2.0.tgz#ba8df5fb841eb0a3e8044232b0e263a8dc6a28a2" + integrity sha1-uo31+4QesKPoBEIysOJjqNxqKKI= + +lodash.bind@^4.1.4: + version "4.2.1" + resolved "https://registry.yarnpkg.com/lodash.bind/-/lodash.bind-4.2.1.tgz#7ae3017e939622ac31b7d7d7dcb1b34db1690d35" + integrity sha1-euMBfpOWIqwxt9fX3LGzTbFpDTU= + +lodash.chunk@^4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.chunk/-/lodash.chunk-4.2.0.tgz#66e5ce1f76ed27b4303d8c6512e8d1216e8106bc" + integrity sha1-ZuXOH3btJ7QwPYxlEujRIW6BBrw= + +lodash.defaults@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" + integrity sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw= + +lodash.filter@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.filter/-/lodash.filter-4.6.0.tgz#668b1d4981603ae1cc5a6fa760143e480b4c4ace" + integrity sha1-ZosdSYFgOuHMWm+nYBQ+SAtMSs4= + +lodash.flatten@^4.2.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f" + integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8= + +lodash.foreach@^4.3.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.foreach/-/lodash.foreach-4.5.0.tgz#1a6a35eace401280c7f06dddec35165ab27e3e53" + integrity sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM= + +lodash.map@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.map/-/lodash.map-4.6.0.tgz#771ec7839e3473d9c4cde28b19394c3562f4f6d3" + integrity sha1-dx7Hg540c9nEzeKLGTlMNWL09tM= + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= + +lodash.merge@^4.4.0: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lodash.padstart@^4.6.1: + version "4.6.1" + resolved "https://registry.yarnpkg.com/lodash.padstart/-/lodash.padstart-4.6.1.tgz#d2e3eebff0d9d39ad50f5cbd1b52a7bce6bb611b" + integrity sha1-0uPuv/DZ05rVD1y9G1KnvOa7YRs= + +lodash.pick@^4.2.1: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.pick/-/lodash.pick-4.4.0.tgz#52f05610fff9ded422611441ed1fc123a03001b3" + integrity sha1-UvBWEP/53tQiYRRB7R/BI6AwAbM= + +lodash.reduce@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.reduce/-/lodash.reduce-4.6.0.tgz#f1ab6b839299ad48f784abbf476596f03b914d3b" + integrity sha1-8atrg5KZrUj3hKu/R2WW8DuRTTs= + +lodash.reject@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.reject/-/lodash.reject-4.6.0.tgz#80d6492dc1470864bbf583533b651f42a9f52415" + integrity sha1-gNZJLcFHCGS79YNTO2UfQqn1JBU= + +lodash.some@^4.4.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/lodash.some/-/lodash.some-4.6.0.tgz#1bb9f314ef6b8baded13b549169b2a945eb68e4d" + integrity sha1-G7nzFO9ri63tE7VJFpsqlF62jk0= + +lodash.sortby@^4.7.0: + version "4.7.0" + resolved "https://registry.yarnpkg.com/lodash.sortby/-/lodash.sortby-4.7.0.tgz#edd14c824e2cc9c1e0b0a1b42bb5210516a42438" + integrity sha1-7dFMgk4sycHgsKG0K7UhBRakJDg= + +lodash.template@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.template/-/lodash.template-4.5.0.tgz#f976195cf3f347d0d5f52483569fe8031ccce8ab" + integrity sha512-84vYFxIkmidUiFxidA/KjjH9pAycqW+h980j7Fuz5qxRtO9pgB7MDFTdys1N7A5mcucRiDyEq4fusljItR1T/A== + dependencies: + lodash._reinterpolate "^3.0.0" + lodash.templatesettings "^4.0.0" + +lodash.templatesettings@^4.0.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/lodash.templatesettings/-/lodash.templatesettings-4.2.0.tgz#e481310f049d3cf6d47e912ad09313b154f0fb33" + integrity sha512-stgLz+i3Aa9mZgnjr/O+v9ruKZsPsndy7qPZOchbqk2cnTU1ZaldKK+v7m54WoKIyxiuMZTKT2H81F8BeAc3ZQ== + dependencies: + lodash._reinterpolate "^3.0.0" + +lodash.toarray@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.toarray/-/lodash.toarray-4.4.0.tgz#24c4bfcd6b2fba38bfd0594db1179d8e9b656561" + integrity sha1-JMS/zWsvuji/0FlNsRedjptlZWE= + +lodash.uniq@4.5.0, lodash.uniq@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" + integrity sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= + +lodash@^4.17.11, lodash@^4.17.12, lodash@^4.17.13, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.5: + version "4.17.15" + resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" + integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== + +loglevel@^1.6.6: + version "1.6.7" + resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.6.7.tgz#b3e034233188c68b889f5b862415306f565e2c56" + integrity sha512-cY2eLFrQSAfVPhCgH1s7JI73tMbg9YC3v3+ZHVW67sBS7UxWzNEk/ZBbSfLykBWHp33dqqtOv82gjhKEi81T/A== + +loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.2.0, loose-envify@^1.3.1, loose-envify@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf" + integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q== + dependencies: + js-tokens "^3.0.0 || ^4.0.0" + +lower-case@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/lower-case/-/lower-case-1.1.4.tgz#9a2cabd1b9e8e0ae993a4bf7d5875c39c42e8eac" + integrity sha1-miyr0bno4K6ZOkv31YdcOcQujqw= + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +make-dir@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-2.1.0.tgz#5f0310e18b8be898cc07009295a30ae41e91e6f5" + integrity sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA== + dependencies: + pify "^4.0.1" + semver "^5.6.0" + +make-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.0.0.tgz#1b5f39f6b9270ed33f9f054c5c0f84304989f801" + integrity sha512-grNJDhb8b1Jm1qeqW5R/O63wUo4UXo2v2HMic6YT9i/HBlF93S8jkMgH7yugvY9ABDShH4VZMn8I+U8+fCNegw== + dependencies: + semver "^6.0.0" + +mamacro@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/mamacro/-/mamacro-0.0.3.tgz#ad2c9576197c9f1abf308d0787865bd975a3f3e4" + integrity sha512-qMEwh+UujcQ+kbz3T6V+wAmO2U8veoq2w+3wY8MquqwVA3jChfwY+Tk52GZKDfACEPjuZ7r2oJLejwpt8jtwTA== + +map-age-cleaner@^0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz#7d583a7306434c055fe474b0f45078e6e1b4b92a" + integrity sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w== + dependencies: + p-defer "^1.0.0" + +map-cache@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/map-cache/-/map-cache-0.2.2.tgz#c32abd0bd6525d9b051645bb4f26ac5dc98a0dbf" + integrity sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= + +map-visit@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/map-visit/-/map-visit-1.0.0.tgz#ecdca8f13144e660f1b5bd41f12f3479d98dfb8f" + integrity sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= + dependencies: + object-visit "^1.0.0" + +markdown-escapes@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/markdown-escapes/-/markdown-escapes-1.0.4.tgz#c95415ef451499d7602b91095f3c8e8975f78535" + integrity sha512-8z4efJYk43E0upd0NbVXwgSTQs6cT3T06etieCMEg7dRbzCbxUCK/GHlX8mhHRDcp+OLlHkPKsvqQTCvsRl2cg== + +md5.js@^1.3.4: + version "1.3.5" + resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" + integrity sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + safe-buffer "^5.1.2" + +mdast-squeeze-paragraphs@^3.0.0: + version "3.0.5" + resolved "https://registry.yarnpkg.com/mdast-squeeze-paragraphs/-/mdast-squeeze-paragraphs-3.0.5.tgz#f428b6b944f8faef454db9b58f170c4183cb2e61" + integrity sha512-xX6Vbe348Y/rukQlG4W3xH+7v4ZlzUbSY4HUIQCuYrF2DrkcHx584mCaFxkWoDZKNUfyLZItHC9VAqX3kIP7XA== + dependencies: + unist-util-remove "^1.0.0" + +mdast-util-definitions@^1.2.0: + version "1.2.5" + resolved "https://registry.yarnpkg.com/mdast-util-definitions/-/mdast-util-definitions-1.2.5.tgz#3fe622a4171c774ebd06f11e9f8af7ec53ea5c74" + integrity sha512-CJXEdoLfiISCDc2JB6QLb79pYfI6+GcIH+W2ox9nMc7od0Pz+bovcHsiq29xAQY6ayqe/9CsK2VzkSJdg1pFYA== + dependencies: + unist-util-visit "^1.0.0" + +mdast-util-to-hast@6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/mdast-util-to-hast/-/mdast-util-to-hast-6.0.2.tgz#24a8791b7c624118637d70f03a9d29116e4311cf" + integrity sha512-GjcOimC9qHI0yNFAQdBesrZXzUkRdFleQlcoU8+TVNfDW6oLUazUx8MgUoTaUyCJzBOnE5AOgqhpURrSlf0QwQ== + dependencies: + collapse-white-space "^1.0.0" + detab "^2.0.0" + mdast-util-definitions "^1.2.0" + mdurl "^1.0.1" + trim "0.0.1" + trim-lines "^1.0.0" + unist-builder "^1.0.1" + unist-util-generated "^1.1.0" + unist-util-position "^3.0.0" + unist-util-visit "^1.1.0" + xtend "^4.0.1" + +mdast-util-to-string@^1.0.0, mdast-util-to-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/mdast-util-to-string/-/mdast-util-to-string-1.0.7.tgz#62d8e9c6b2113070d8b497c7dc35bf12796f06ee" + integrity sha512-P+gdtssCoHOX+eJUrrC30Sixqao86ZPlVjR5NEAoy0U79Pfxb1Y0Gntei0+GrnQD4T04X9xA8tcugp90cSmNow== + +mdn-data@2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.0.4.tgz#699b3c38ac6f1d728091a64650b65d388502fd5b" + integrity sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA== + +mdurl@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/mdurl/-/mdurl-1.0.1.tgz#fe85b2ec75a59037f2adfec100fd6c601761152e" + integrity sha1-/oWy7HWlkDfyrf7BAP1sYBdhFS4= + +media-typer@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" + integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= + +mem@^4.0.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/mem/-/mem-4.3.0.tgz#461af497bc4ae09608cdb2e60eefb69bff744178" + integrity sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w== + dependencies: + map-age-cleaner "^0.1.1" + mimic-fn "^2.0.0" + p-is-promise "^2.0.0" + +memory-fs@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.4.1.tgz#3a9a20b8462523e447cfbc7e8bb80ed667bfc552" + integrity sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +memory-fs@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/memory-fs/-/memory-fs-0.5.0.tgz#324c01288b88652966d161db77838720845a8e3c" + integrity sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA== + dependencies: + errno "^0.1.3" + readable-stream "^2.0.1" + +merge-descriptors@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" + integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.2.3, merge2@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.3.0.tgz#5b366ee83b2f1582c48f87e47cf1a9352103ca81" + integrity sha512-2j4DAdlBOkiSZIsaXk4mTE3sRS02yBHAtfy127xRV3bQUFqXkjHCHLW6Scv7DwNRbIWNHH8zpnz9zMaKXIdvYw== + +methods@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" + integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= + +microevent.ts@~0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/microevent.ts/-/microevent.ts-0.1.1.tgz#70b09b83f43df5172d0205a63025bce0f7357fa0" + integrity sha512-jo1OfR4TaEwd5HOrt5+tAZ9mqT4jmpNAusXtyfNzqVm9uiSYFZlKM1wYL4oU7azZW/PxQW53wM0S6OR1JHNa2g== + +micromatch@^3.1.10, micromatch@^3.1.4: + version "3.1.10" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23" + integrity sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + braces "^2.3.1" + define-property "^2.0.2" + extend-shallow "^3.0.2" + extglob "^2.0.4" + fragment-cache "^0.2.1" + kind-of "^6.0.2" + nanomatch "^1.2.9" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.2" + +micromatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.2.tgz#4fcb0999bf9fbc2fcbdd212f6d629b9a56c39259" + integrity sha512-y7FpHSbMUMoyPbYUSzO6PaZ6FyRnQOpHuKwbo1G+Knck95XVU4QAiKdGEnj5wwoS7PlOgthX/09u5iFJ+aYf5Q== + dependencies: + braces "^3.0.1" + picomatch "^2.0.5" + +miller-rabin@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/miller-rabin/-/miller-rabin-4.0.1.tgz#f080351c865b0dc562a8462966daa53543c78a4d" + integrity sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA== + dependencies: + bn.js "^4.0.0" + brorand "^1.0.1" + +mime-db@1.43.0, "mime-db@>= 1.43.0 < 2": + version "1.43.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" + integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== + +mime-types@^2.1.12, mime-types@~2.1.17, mime-types@~2.1.19, mime-types@~2.1.24: + version "2.1.26" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" + integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== + dependencies: + mime-db "1.43.0" + +mime@1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" + integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== + +mime@^2.4.4: + version "2.4.4" + resolved "https://registry.yarnpkg.com/mime/-/mime-2.4.4.tgz#bd7b91135fc6b01cde3e9bae33d659b63d8857e5" + integrity sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA== + +mimic-fn@^1.0.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-1.2.0.tgz#820c86a39334640e99516928bd03fca88057d022" + integrity sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ== + +mimic-fn@^2.0.0, mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +min-document@^2.19.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685" + integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU= + dependencies: + dom-walk "^0.1.0" + +mini-create-react-context@^0.3.0: + version "0.3.2" + resolved "https://registry.yarnpkg.com/mini-create-react-context/-/mini-create-react-context-0.3.2.tgz#79fc598f283dd623da8e088b05db8cddab250189" + integrity sha512-2v+OeetEyliMt5VHMXsBhABoJ0/M4RCe7fatd/fBy6SMiKazUSEt3gxxypfnk2SHMkdBYvorHRoQxuGoiwbzAw== + dependencies: + "@babel/runtime" "^7.4.0" + gud "^1.0.0" + tiny-warning "^1.0.2" + +mini-css-extract-plugin@^0.8.0: + version "0.8.2" + resolved "https://registry.yarnpkg.com/mini-css-extract-plugin/-/mini-css-extract-plugin-0.8.2.tgz#a875e169beb27c88af77dd962771c9eedc3da161" + integrity sha512-a3Y4of27Wz+mqK3qrcd3VhYz6cU0iW5x3Sgvqzbj+XmlrSizmvu8QQMl5oMYJjgHOC4iyt+w7l4umP+dQeW3bw== + dependencies: + loader-utils "^1.1.0" + normalize-url "1.9.1" + schema-utils "^1.0.0" + webpack-sources "^1.1.0" + +minimalistic-assert@^1.0.0, minimalistic-assert@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7" + integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A== + +minimalistic-crypto-utils@^1.0.0, minimalistic-crypto-utils@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz#f6c00c1c0b082246e5c4d99dfb8c7c083b2b582a" + integrity sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= + +minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +minimist@0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d" + integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0= + +minimist@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284" + integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ= + +minipass-collect@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/minipass-collect/-/minipass-collect-1.0.2.tgz#22b813bf745dc6edba2576b940022ad6edc8c617" + integrity sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA== + dependencies: + minipass "^3.0.0" + +minipass-flush@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/minipass-flush/-/minipass-flush-1.0.5.tgz#82e7135d7e89a50ffe64610a787953c4c4cbb373" + integrity sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw== + dependencies: + minipass "^3.0.0" + +minipass-pipeline@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/minipass-pipeline/-/minipass-pipeline-1.2.2.tgz#3dcb6bb4a546e32969c7ad710f2c79a86abba93a" + integrity sha512-3JS5A2DKhD2g0Gg8x3yamO0pj7YeKGwVlDS90pF++kxptwx/F+B//roxf9SqYil5tQo65bijy+dAuAFZmYOouA== + dependencies: + minipass "^3.0.0" + +minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" + integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== + dependencies: + safe-buffer "^5.1.2" + yallist "^3.0.0" + +minipass@^3.0.0, minipass@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-3.1.1.tgz#7607ce778472a185ad6d89082aa2070f79cedcd5" + integrity sha512-UFqVihv6PQgwj8/yTGvl9kPz7xIAY+R5z6XYjRInD3Gk3qx6QGSD6zEcpeG4Dy/lQnv1J6zv8ejV90hyYIKf3w== + dependencies: + yallist "^4.0.0" + +minizlib@^1.2.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" + integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== + dependencies: + minipass "^2.9.0" + +mississippi@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mississippi/-/mississippi-3.0.0.tgz#ea0a3291f97e0b5e8776b363d5f0a12d94c67022" + integrity sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA== + dependencies: + concat-stream "^1.5.0" + duplexify "^3.4.2" + end-of-stream "^1.1.0" + flush-write-stream "^1.0.0" + from2 "^2.1.0" + parallel-transform "^1.1.0" + pump "^3.0.0" + pumpify "^1.3.3" + stream-each "^1.1.0" + through2 "^2.0.0" + +mixin-deep@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/mixin-deep/-/mixin-deep-1.3.2.tgz#1120b43dc359a785dce65b55b82e257ccf479566" + integrity sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA== + dependencies: + for-in "^1.0.2" + is-extendable "^1.0.1" + +mkdirp@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.3.0.tgz#1bbf5ab1ba827af23575143490426455f481fe1e" + integrity sha1-G79asbqCevI1dRQ0kEJkVfSB/h4= + +mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@~0.5.1: + version "0.5.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903" + integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM= + dependencies: + minimist "0.0.8" + +move-concurrently@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/move-concurrently/-/move-concurrently-1.0.1.tgz#be2c005fda32e0b29af1f05d7c4b33214c701f92" + integrity sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= + dependencies: + aproba "^1.1.1" + copy-concurrently "^1.0.0" + fs-write-stream-atomic "^1.0.8" + mkdirp "^0.5.1" + rimraf "^2.5.4" + run-queue "^1.0.3" + +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= + +ms@2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" + integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== + +ms@^2.1.1: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +multicast-dns-service-types@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz#899f11d9686e5e05cb91b35d5f0e63b773cfc901" + integrity sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= + +multicast-dns@^6.0.1: + version "6.2.3" + resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-6.2.3.tgz#a0ec7bd9055c4282f790c3c82f4e28db3b31b229" + integrity sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g== + dependencies: + dns-packet "^1.3.1" + thunky "^1.0.2" + +mute-stream@0.0.7: + version "0.0.7" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.7.tgz#3075ce93bc21b8fab43e1bc4da7e8115ed1e7bab" + integrity sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s= + +nan@^2.12.1: + version "2.14.0" + resolved "https://registry.yarnpkg.com/nan/-/nan-2.14.0.tgz#7818f722027b2459a86f0295d434d1fc2336c52c" + integrity sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg== + +nanomatch@^1.2.9: + version "1.2.13" + resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" + integrity sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA== + dependencies: + arr-diff "^4.0.0" + array-unique "^0.3.2" + define-property "^2.0.2" + extend-shallow "^3.0.2" + fragment-cache "^0.2.1" + is-windows "^1.0.2" + kind-of "^6.0.2" + object.pick "^1.3.0" + regex-not "^1.0.0" + snapdragon "^0.8.1" + to-regex "^3.0.1" + +needle@^2.2.1: + version "2.3.2" + resolved "https://registry.yarnpkg.com/needle/-/needle-2.3.2.tgz#3342dea100b7160960a450dc8c22160ac712a528" + integrity sha512-DUzITvPVDUy6vczKKYTnWc/pBZ0EnjMJnQ3y+Jo5zfKFimJs7S3HFCxCRZYB9FUZcrzUQr3WsmvZgddMEIZv6w== + dependencies: + debug "^3.2.6" + iconv-lite "^0.4.4" + sax "^1.2.4" + +negotiator@0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" + integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== + +neo-async@^2.5.0, neo-async@^2.6.1: + version "2.6.1" + resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.6.1.tgz#ac27ada66167fa8849a6addd837f6b189ad2081c" + integrity sha512-iyam8fBuCUpWeKPGpaNMetEocMt364qkCsfL9JuhjXX6dRnguRVOfk2GZaDpPjcOKiiXCPINZC1GczQ7iTq3Zw== + +nice-try@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/nice-try/-/nice-try-1.0.5.tgz#a3378a7696ce7d223e88fc9b764bd7ef1089e366" + integrity sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ== + +no-case@^2.2.0: + version "2.3.2" + resolved "https://registry.yarnpkg.com/no-case/-/no-case-2.3.2.tgz#60b813396be39b3f1288a4c1ed5d1e7d28b464ac" + integrity sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ== + dependencies: + lower-case "^1.1.1" + +node-emoji@^1.8.1: + version "1.10.0" + resolved "https://registry.yarnpkg.com/node-emoji/-/node-emoji-1.10.0.tgz#8886abd25d9c7bb61802a658523d1f8d2a89b2da" + integrity sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw== + dependencies: + lodash.toarray "^4.4.0" + +node-forge@0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.9.0.tgz#d624050edbb44874adca12bb9a52ec63cb782579" + integrity sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ== + +node-libs-browser@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/node-libs-browser/-/node-libs-browser-2.2.1.tgz#b64f513d18338625f90346d27b0d235e631f6425" + integrity sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q== + dependencies: + assert "^1.1.1" + browserify-zlib "^0.2.0" + buffer "^4.3.0" + console-browserify "^1.1.0" + constants-browserify "^1.0.0" + crypto-browserify "^3.11.0" + domain-browser "^1.1.1" + events "^3.0.0" + https-browserify "^1.0.0" + os-browserify "^0.3.0" + path-browserify "0.0.1" + process "^0.11.10" + punycode "^1.2.4" + querystring-es3 "^0.2.0" + readable-stream "^2.3.3" + stream-browserify "^2.0.1" + stream-http "^2.7.2" + string_decoder "^1.0.0" + timers-browserify "^2.0.4" + tty-browserify "0.0.0" + url "^0.11.0" + util "^0.11.0" + vm-browserify "^1.0.1" + +node-pre-gyp@*: + version "0.14.0" + resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.14.0.tgz#9a0596533b877289bcad4e143982ca3d904ddc83" + integrity sha512-+CvDC7ZttU/sSt9rFjix/P05iS43qHCOOGzcr3Ry99bXG7VX953+vFyEuph/tfqoYu8dttBkE86JSKBO2OzcxA== + dependencies: + detect-libc "^1.0.2" + mkdirp "^0.5.1" + needle "^2.2.1" + nopt "^4.0.1" + npm-packlist "^1.1.6" + npmlog "^4.0.2" + rc "^1.2.7" + rimraf "^2.6.1" + semver "^5.3.0" + tar "^4.4.2" + +node-releases@^1.1.29, node-releases@^1.1.47: + version "1.1.49" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.49.tgz#67ba5a3fac2319262675ef864ed56798bb33b93e" + integrity sha512-xH8t0LS0disN0mtRCh+eByxFPie+msJUBL/lJDBuap53QGiYPa9joh83K4pCZgWJ+2L4b9h88vCVdXQ60NO2bg== + dependencies: + semver "^6.3.0" + +nopt@1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee" + integrity sha1-bd0hvSoxQXuScn3Vhfim83YI6+4= + dependencies: + abbrev "1" + +nopt@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.1.tgz#d0d4685afd5415193c8c7505602d0d17cd64474d" + integrity sha1-0NRoWv1UFRk8jHUFYC0NF81kR00= + dependencies: + abbrev "1" + osenv "^0.1.4" + +normalize-path@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-2.1.1.tgz#1ab28b556e198363a8c1a6f7e6fa20137fe6aed9" + integrity sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= + dependencies: + remove-trailing-separator "^1.0.1" + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +normalize-range@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" + integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= + +normalize-url@1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c" + integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= + dependencies: + object-assign "^4.0.1" + prepend-http "^1.0.0" + query-string "^4.1.0" + sort-keys "^1.0.0" + +normalize-url@^3.0.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" + integrity sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg== + +npm-bundled@^1.0.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/npm-bundled/-/npm-bundled-1.1.1.tgz#1edd570865a94cdb1bc8220775e29466c9fb234b" + integrity sha512-gqkfgGePhTpAEgUsGEgcq1rqPXA+tv/aVBlgEzfXwA1yiUJF7xtEt3CtVwOjNYQOVknDk0F20w58Fnm3EtG0fA== + dependencies: + npm-normalize-package-bin "^1.0.1" + +npm-normalize-package-bin@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/npm-normalize-package-bin/-/npm-normalize-package-bin-1.0.1.tgz#6e79a41f23fd235c0623218228da7d9c23b8f6e2" + integrity sha512-EPfafl6JL5/rU+ot6P3gRSCpPDW5VmIzX959Ob1+ySFUuuYHWHekXpwdUZcKP5C+DS4GEtdJluwBjnsNDl+fSA== + +npm-packlist@^1.1.6: + version "1.4.8" + resolved "https://registry.yarnpkg.com/npm-packlist/-/npm-packlist-1.4.8.tgz#56ee6cc135b9f98ad3d51c1c95da22bbb9b2ef3e" + integrity sha512-5+AZgwru5IevF5ZdnFglB5wNlHG1AOOuw28WhUq8/8emhBmLv6jX5by4WJCh7lW0uSYZYS6DXqIsyZVIXRZU9A== + dependencies: + ignore-walk "^3.0.1" + npm-bundled "^1.0.1" + npm-normalize-package-bin "^1.0.1" + +npm-run-path@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-2.0.2.tgz#35a9232dfa35d7067b4cb2ddf2357b1871536c5f" + integrity sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= + dependencies: + path-key "^2.0.0" + +npm-run-path@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + +npmlog@^4.0.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" + integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== + dependencies: + are-we-there-yet "~1.1.2" + console-control-strings "~1.1.0" + gauge "~2.7.3" + set-blocking "~2.0.0" + +nprogress@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/nprogress/-/nprogress-0.2.0.tgz#cb8f34c53213d895723fcbab907e9422adbcafb1" + integrity sha1-y480xTIT2JVyP8urkH6UIq28r7E= + +nth-check@^1.0.2, nth-check@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-1.0.2.tgz#b2bd295c37e3dd58a3bf0700376663ba4d9cf05c" + integrity sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg== + dependencies: + boolbase "~1.0.0" + +null-loader@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/null-loader/-/null-loader-3.0.0.tgz#3e2b6c663c5bda8c73a54357d8fa0708dc61b245" + integrity sha512-hf5sNLl8xdRho4UPBOOeoIwT3WhjYcMUQm0zj44EhD6UscMAz72o2udpoDFBgykucdEDGIcd6SXbc/G6zssbzw== + dependencies: + loader-utils "^1.2.3" + schema-utils "^1.0.0" + +num2fraction@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede" + integrity sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= + +number-is-nan@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" + integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= + +oauth-sign@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" + integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== + +object-assign@^4.0.1, object-assign@^4.1.0, object-assign@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" + integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= + +object-copy@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/object-copy/-/object-copy-0.1.0.tgz#7e7d858b781bd7c991a41ba975ed3812754e998c" + integrity sha1-fn2Fi3gb18mRpBupde04EnVOmYw= + dependencies: + copy-descriptor "^0.1.0" + define-property "^0.2.5" + kind-of "^3.0.3" + +object-inspect@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.7.0.tgz#f4f6bd181ad77f006b5ece60bd0b6f398ff74a67" + integrity sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw== + +object-is@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.0.2.tgz#6b80eb84fe451498f65007982f035a5b445edec4" + integrity sha512-Epah+btZd5wrrfjkJZq1AOB9O6OxUQto45hzFd7lXGrpHPGE0W1k+426yrZV+k6NJOzLNNW/nVsmZdIWsAqoOQ== + +object-keys@^1.0.11, object-keys@^1.0.12, object-keys@^1.1.0, object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object-visit@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object-visit/-/object-visit-1.0.1.tgz#f79c4493af0c5377b59fe39d395e41042dd045bb" + integrity sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= + dependencies: + isobject "^3.0.0" + +object.assign@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.0.tgz#968bf1100d7956bb3ca086f006f846b3bc4008da" + integrity sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w== + dependencies: + define-properties "^1.1.2" + function-bind "^1.1.1" + has-symbols "^1.0.0" + object-keys "^1.0.11" + +object.getownpropertydescriptors@^2.0.3, object.getownpropertydescriptors@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz#369bf1f9592d8ab89d712dced5cb81c7c5352649" + integrity sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + +object.pick@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/object.pick/-/object.pick-1.3.0.tgz#87a10ac4c1694bd2e1cbf53591a66141fb5dd747" + integrity sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= + dependencies: + isobject "^3.0.1" + +object.values@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.1.tgz#68a99ecde356b7e9295a3c5e0ce31dc8c953de5e" + integrity sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + function-bind "^1.1.1" + has "^1.0.3" + +obuf@^1.0.0, obuf@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e" + integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg== + +on-finished@~2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" + integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= + dependencies: + ee-first "1.1.1" + +on-headers@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.0.2.tgz#772b0ae6aaa525c399e489adfad90c403eb3c28f" + integrity sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA== + +once@^1.3.0, once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +onetime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-2.0.1.tgz#067428230fd67443b2794b22bba528b6867962d4" + integrity sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= + dependencies: + mimic-fn "^1.0.0" + +onetime@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.0.tgz#fff0f3c91617fe62bb50189636e99ac8a6df7be5" + integrity sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q== + dependencies: + mimic-fn "^2.1.0" + +open@^6.3.0: + version "6.4.0" + resolved "https://registry.yarnpkg.com/open/-/open-6.4.0.tgz#5c13e96d0dc894686164f18965ecfe889ecfc8a9" + integrity sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg== + dependencies: + is-wsl "^1.1.0" + +opener@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/opener/-/opener-1.5.1.tgz#6d2f0e77f1a0af0032aca716c2c1fbb8e7e8abed" + integrity sha512-goYSy5c2UXE4Ra1xixabeVh1guIX/ZV/YokJksb6q2lubWu6UbvPQ20p542/sFIll1nl8JnCyK9oBaOcCWXwvA== + +opn@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/opn/-/opn-5.5.0.tgz#fc7164fab56d235904c51c3b27da6758ca3b9bfc" + integrity sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA== + dependencies: + is-wsl "^1.1.0" + +optimize-css-assets-webpack-plugin@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/optimize-css-assets-webpack-plugin/-/optimize-css-assets-webpack-plugin-5.0.3.tgz#e2f1d4d94ad8c0af8967ebd7cf138dcb1ef14572" + integrity sha512-q9fbvCRS6EYtUKKSwI87qm2IxlyJK5b4dygW1rKUBT6mMDhdG5e5bZT63v6tnJR9F9FB/H5a0HTmtw+laUBxKA== + dependencies: + cssnano "^4.1.10" + last-call-webpack-plugin "^3.0.0" + +original@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/original/-/original-1.0.2.tgz#e442a61cffe1c5fd20a65f3261c26663b303f25f" + integrity sha512-hyBVl6iqqUOJ8FqRe+l/gS8H+kKYjrEndd5Pm1MfBtsEKA038HkkdbAl/72EAXGyonD/PFsvmVG+EvcIpliMBg== + dependencies: + url-parse "^1.4.3" + +os-browserify@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27" + integrity sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= + +os-homedir@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" + integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= + +os-locale@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/os-locale/-/os-locale-3.1.0.tgz#a802a6ee17f24c10483ab9935719cef4ed16bf1a" + integrity sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q== + dependencies: + execa "^1.0.0" + lcid "^2.0.0" + mem "^4.0.0" + +os-tmpdir@^1.0.0, os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= + +osenv@^0.1.4: + version "0.1.5" + resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" + integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== + dependencies: + os-homedir "^1.0.0" + os-tmpdir "^1.0.0" + +p-defer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-defer/-/p-defer-1.0.0.tgz#9f6eb182f6c9aa8cd743004a7d4f96b196b0fb0c" + integrity sha1-n26xgvbJqozXQwBKfU+WsZaw+ww= + +p-finally@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-1.0.0.tgz#3fbcfb15b899a44123b34b6dcc18b724336a2cae" + integrity sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= + +p-finally@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/p-finally/-/p-finally-2.0.1.tgz#bd6fcaa9c559a096b680806f4d657b3f0f240561" + integrity sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw== + +p-is-promise@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-is-promise/-/p-is-promise-2.1.0.tgz#918cebaea248a62cf7ffab8e3bca8c5f882fc42e" + integrity sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg== + +p-limit@^1.1.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" + integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q== + dependencies: + p-try "^1.0.0" + +p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.1, p-limit@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.2.2.tgz#61279b67721f5287aa1c13a9a7fbbc48c9291b1e" + integrity sha512-WGR+xHecKTr7EbUEhyLSh5Dube9JtdiG78ufaeLxTgpudf/20KqyMioIUZJAezlTIi6evxuoUs9YXc11cU+yzQ== + dependencies: + p-try "^2.0.0" + +p-locate@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" + integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM= + dependencies: + p-limit "^1.1.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-map@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-2.1.0.tgz#310928feef9c9ecc65b68b17693018a665cea175" + integrity sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw== + +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + +p-retry@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/p-retry/-/p-retry-3.0.1.tgz#316b4c8893e2c8dc1cfa891f406c4b422bebf328" + integrity sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w== + dependencies: + retry "^0.12.0" + +p-try@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3" + integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M= + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +pako@~1.0.5: + version "1.0.11" + resolved "https://registry.yarnpkg.com/pako/-/pako-1.0.11.tgz#6c9599d340d54dfd3946380252a35705a6b992bf" + integrity sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw== + +parallel-transform@^1.1.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/parallel-transform/-/parallel-transform-1.2.0.tgz#9049ca37d6cb2182c3b1d2c720be94d14a5814fc" + integrity sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg== + dependencies: + cyclist "^1.0.1" + inherits "^2.0.3" + readable-stream "^2.1.5" + +param-case@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/param-case/-/param-case-2.1.1.tgz#df94fd8cf6531ecf75e6bef9a0858fbc72be2247" + integrity sha1-35T9jPZTHs915r75oIWPvHK+Ikc= + dependencies: + no-case "^2.2.0" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +parse-asn1@^5.0.0: + version "5.1.5" + resolved "https://registry.yarnpkg.com/parse-asn1/-/parse-asn1-5.1.5.tgz#003271343da58dc94cace494faef3d2147ecea0e" + integrity sha512-jkMYn1dcJqF6d5CpU689bq7w/b5ALS9ROVSpQDPrZsqqesUJii9qutvoT5ltGedNXMO2e16YUWIghG9KxaViTQ== + dependencies: + asn1.js "^4.0.0" + browserify-aes "^1.0.0" + create-hash "^1.1.0" + evp_bytestokey "^1.0.0" + pbkdf2 "^3.0.3" + safe-buffer "^5.1.1" + +parse-entities@^1.1.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-1.2.2.tgz#c31bf0f653b6661354f8973559cb86dd1d5edf50" + integrity sha512-NzfpbxW/NPrzZ/yYSoQxyqUZMZXIdCfE0OIN4ESsnptHJECoUk3FZktxNuzQf4tjt5UEopnxpYJbvYuxIFDdsg== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + +parse-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/parse-json/-/parse-json-4.0.0.tgz#be35f5425be1f7f6c747184f98a788cb99477ee0" + integrity sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= + dependencies: + error-ex "^1.3.1" + json-parse-better-errors "^1.0.1" + +parse-numeric-range@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/parse-numeric-range/-/parse-numeric-range-0.0.2.tgz#b4f09d413c7adbcd987f6e9233c7b4b210c938e4" + integrity sha1-tPCdQTx6282Yf26SM8e0shDJOOQ= + +parse5@^5.0.0: + version "5.1.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-5.1.1.tgz#f68e4e5ba1852ac2cadc00f4555fff6c2abb6178" + integrity sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug== + +parseurl@~1.3.2, parseurl@~1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" + integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== + +pascalcase@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/pascalcase/-/pascalcase-0.1.1.tgz#b363e55e8006ca6fe21784d2db22bd15d7917f14" + integrity sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= + +path-browserify@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-0.0.1.tgz#e6c4ddd7ed3aa27c68a20cc4e50e1a4ee83bbc4a" + integrity sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ== + +path-dirname@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-dirname/-/path-dirname-1.0.2.tgz#cc33d24d525e099a5388c0336c6e32b9160609e0" + integrity sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +path-is-inside@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= + +path-key@^2.0.0, path-key@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-2.0.1.tgz#411cadb574c5a140d3a4b1910d40d80cc9f40b40" + integrity sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= + +path-key@^3.0.0, path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-parse@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" + integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== + +path-to-regexp@0.1.7: + version "0.1.7" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" + integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= + +path-to-regexp@^1.7.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" + integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== + dependencies: + isarray "0.0.1" + +path-type@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-3.0.0.tgz#cef31dc8e0a1a3bb0d105c0cd97cf3bf47f4e36f" + integrity sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg== + dependencies: + pify "^3.0.0" + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pbkdf2@^3.0.3: + version "3.0.17" + resolved "https://registry.yarnpkg.com/pbkdf2/-/pbkdf2-3.0.17.tgz#976c206530617b14ebb32114239f7b09336e93a6" + integrity sha512-U/il5MsrZp7mGg3mSQfn742na2T+1/vHDCG5/iTI3X9MKUuYUZVLQhyRsg06mCgDBTd57TxzgZt7P+fYfjRLtA== + dependencies: + create-hash "^1.1.2" + create-hmac "^1.1.4" + ripemd160 "^2.0.1" + safe-buffer "^5.0.1" + sha.js "^2.4.8" + +performance-now@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" + integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= + +picomatch@^2.0.4, picomatch@^2.0.5, picomatch@^2.0.7: + version "2.2.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.2.1.tgz#21bac888b6ed8601f831ce7816e335bc779f0a4a" + integrity sha512-ISBaA8xQNmwELC7eOjqFKMESB2VIqt4PPDD0nsS95b/9dZXvVKOlz9keMSnoGGKcOHXfTvDD6WMaRoSc9UuhRA== + +pify@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c" + integrity sha1-7RQaasBDqEnqWISY59yosVMw6Qw= + +pify@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176" + integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= + +pify@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/pify/-/pify-4.0.1.tgz#4b2cd25c50d598735c50292224fd8c6df41e3231" + integrity sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g== + +pinkie-promise@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pinkie-promise/-/pinkie-promise-2.0.1.tgz#2135d6dfa7a358c069ac9b178776288228450ffa" + integrity sha1-ITXW36ejWMBprJsXh3YogihFD/o= + dependencies: + pinkie "^2.0.0" + +pinkie@^2.0.0: + version "2.0.4" + resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870" + integrity sha1-clVrgM+g1IqXToDnckjoDtT3+HA= + +pkg-dir@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-3.0.0.tgz#2749020f239ed990881b1f71210d51eb6523bea3" + integrity sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw== + dependencies: + find-up "^3.0.0" + +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-up@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f" + integrity sha1-yBmscoBZpGHKscOImivjxJoATX8= + dependencies: + find-up "^2.1.0" + +portfinder@^1.0.25: + version "1.0.25" + resolved "https://registry.yarnpkg.com/portfinder/-/portfinder-1.0.25.tgz#254fd337ffba869f4b9d37edc298059cb4d35eca" + integrity sha512-6ElJnHBbxVA1XSLgBp7G1FiCkQdlqGzuF7DswL5tcea+E8UpuvPU7beVAjjRwCioTS9ZluNbu+ZyRvgTsmqEBg== + dependencies: + async "^2.6.2" + debug "^3.1.1" + mkdirp "^0.5.1" + +posix-character-classes@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/posix-character-classes/-/posix-character-classes-0.1.1.tgz#01eac0fe3b5af71a2a6c02feabb8c1fef7e00eab" + integrity sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= + +postcss-attribute-case-insensitive@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz#d93e46b504589e94ac7277b0463226c68041a880" + integrity sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA== + dependencies: + postcss "^7.0.2" + postcss-selector-parser "^6.0.2" + +postcss-calc@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-calc/-/postcss-calc-7.0.1.tgz#36d77bab023b0ecbb9789d84dcb23c4941145436" + integrity sha512-oXqx0m6tb4N3JGdmeMSc/i91KppbYsFZKdH0xMOqK8V1rJlzrKlTdokz8ozUXLVejydRN6u2IddxpcijRj2FqQ== + dependencies: + css-unit-converter "^1.1.1" + postcss "^7.0.5" + postcss-selector-parser "^5.0.0-rc.4" + postcss-value-parser "^3.3.1" + +postcss-color-functional-notation@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz#5efd37a88fbabeb00a2966d1e53d98ced93f74e0" + integrity sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g== + dependencies: + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-color-gray@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz#532a31eb909f8da898ceffe296fdc1f864be8547" + integrity sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw== + dependencies: + "@csstools/convert-colors" "^1.4.0" + postcss "^7.0.5" + postcss-values-parser "^2.0.0" + +postcss-color-hex-alpha@^5.0.3: + version "5.0.3" + resolved "https://registry.yarnpkg.com/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz#a8d9ca4c39d497c9661e374b9c51899ef0f87388" + integrity sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw== + dependencies: + postcss "^7.0.14" + postcss-values-parser "^2.0.1" + +postcss-color-mod-function@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz#816ba145ac11cc3cb6baa905a75a49f903e4d31d" + integrity sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ== + dependencies: + "@csstools/convert-colors" "^1.4.0" + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-color-rebeccapurple@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz#c7a89be872bb74e45b1e3022bfe5748823e6de77" + integrity sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g== + dependencies: + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-colormin@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-colormin/-/postcss-colormin-4.0.3.tgz#ae060bce93ed794ac71264f08132d550956bd381" + integrity sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw== + dependencies: + browserslist "^4.0.0" + color "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-convert-values@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz#ca3813ed4da0f812f9d43703584e449ebe189a7f" + integrity sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-custom-media@^7.0.8: + version "7.0.8" + resolved "https://registry.yarnpkg.com/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz#fffd13ffeffad73621be5f387076a28b00294e0c" + integrity sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg== + dependencies: + postcss "^7.0.14" + +postcss-custom-properties@^8.0.11: + version "8.0.11" + resolved "https://registry.yarnpkg.com/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz#2d61772d6e92f22f5e0d52602df8fae46fa30d97" + integrity sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA== + dependencies: + postcss "^7.0.17" + postcss-values-parser "^2.0.1" + +postcss-custom-selectors@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz#64858c6eb2ecff2fb41d0b28c9dd7b3db4de7fba" + integrity sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w== + dependencies: + postcss "^7.0.2" + postcss-selector-parser "^5.0.0-rc.3" + +postcss-dir-pseudo-class@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz#6e3a4177d0edb3abcc85fdb6fbb1c26dabaeaba2" + integrity sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw== + dependencies: + postcss "^7.0.2" + postcss-selector-parser "^5.0.0-rc.3" + +postcss-discard-comments@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz#1fbabd2c246bff6aaad7997b2b0918f4d7af4033" + integrity sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg== + dependencies: + postcss "^7.0.0" + +postcss-discard-duplicates@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz#3fe133cd3c82282e550fc9b239176a9207b784eb" + integrity sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ== + dependencies: + postcss "^7.0.0" + +postcss-discard-empty@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz#c8c951e9f73ed9428019458444a02ad90bb9f765" + integrity sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w== + dependencies: + postcss "^7.0.0" + +postcss-discard-overridden@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz#652aef8a96726f029f5e3e00146ee7a4e755ff57" + integrity sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg== + dependencies: + postcss "^7.0.0" + +postcss-double-position-gradients@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz#fc927d52fddc896cb3a2812ebc5df147e110522e" + integrity sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA== + dependencies: + postcss "^7.0.5" + postcss-values-parser "^2.0.0" + +postcss-env-function@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/postcss-env-function/-/postcss-env-function-2.0.2.tgz#0f3e3d3c57f094a92c2baf4b6241f0b0da5365d7" + integrity sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw== + dependencies: + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-focus-visible@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz#477d107113ade6024b14128317ade2bd1e17046e" + integrity sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g== + dependencies: + postcss "^7.0.2" + +postcss-focus-within@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz#763b8788596cee9b874c999201cdde80659ef680" + integrity sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w== + dependencies: + postcss "^7.0.2" + +postcss-font-variant@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-font-variant/-/postcss-font-variant-4.0.0.tgz#71dd3c6c10a0d846c5eda07803439617bbbabacc" + integrity sha512-M8BFYKOvCrI2aITzDad7kWuXXTm0YhGdP9Q8HanmN4EF1Hmcgs1KK5rSHylt/lUJe8yLxiSwWAHdScoEiIxztg== + dependencies: + postcss "^7.0.2" + +postcss-gap-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz#431c192ab3ed96a3c3d09f2ff615960f902c1715" + integrity sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg== + dependencies: + postcss "^7.0.2" + +postcss-image-set-function@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz#28920a2f29945bed4c3198d7df6496d410d3f288" + integrity sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw== + dependencies: + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-initial@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postcss-initial/-/postcss-initial-3.0.2.tgz#f018563694b3c16ae8eaabe3c585ac6319637b2d" + integrity sha512-ugA2wKonC0xeNHgirR4D3VWHs2JcU08WAi1KFLVcnb7IN89phID6Qtg2RIctWbnvp1TM2BOmDtX8GGLCKdR8YA== + dependencies: + lodash.template "^4.5.0" + postcss "^7.0.2" + +postcss-lab-function@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz#bb51a6856cd12289ab4ae20db1e3821ef13d7d2e" + integrity sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg== + dependencies: + "@csstools/convert-colors" "^1.4.0" + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-load-config@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/postcss-load-config/-/postcss-load-config-2.1.0.tgz#c84d692b7bb7b41ddced94ee62e8ab31b417b003" + integrity sha512-4pV3JJVPLd5+RueiVVB+gFOAa7GWc25XQcMp86Zexzke69mKf6Nx9LRcQywdz7yZI9n1udOxmLuAwTBypypF8Q== + dependencies: + cosmiconfig "^5.0.0" + import-cwd "^2.0.0" + +postcss-loader@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-loader/-/postcss-loader-3.0.0.tgz#6b97943e47c72d845fa9e03f273773d4e8dd6c2d" + integrity sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA== + dependencies: + loader-utils "^1.1.0" + postcss "^7.0.0" + postcss-load-config "^2.0.0" + schema-utils "^1.0.0" + +postcss-logical@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-logical/-/postcss-logical-3.0.0.tgz#2495d0f8b82e9f262725f75f9401b34e7b45d5b5" + integrity sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA== + dependencies: + postcss "^7.0.2" + +postcss-media-minmax@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz#b75bb6cbc217c8ac49433e12f22048814a4f5ed5" + integrity sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw== + dependencies: + postcss "^7.0.2" + +postcss-merge-longhand@^4.0.11: + version "4.0.11" + resolved "https://registry.yarnpkg.com/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz#62f49a13e4a0ee04e7b98f42bb16062ca2549e24" + integrity sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw== + dependencies: + css-color-names "0.0.4" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + stylehacks "^4.0.0" + +postcss-merge-rules@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz#362bea4ff5a1f98e4075a713c6cb25aefef9a650" + integrity sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + cssnano-util-same-parent "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + vendors "^1.0.0" + +postcss-minify-font-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz#cd4c344cce474343fac5d82206ab2cbcb8afd5a6" + integrity sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-gradients@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz#93b29c2ff5099c535eecda56c4aa6e665a663471" + integrity sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + is-color-stop "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-minify-params@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz#6b9cef030c11e35261f95f618c90036d680db874" + integrity sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg== + dependencies: + alphanum-sort "^1.0.0" + browserslist "^4.0.0" + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + uniqs "^2.0.0" + +postcss-minify-selectors@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz#e2e5eb40bfee500d0cd9243500f5f8ea4262fbd8" + integrity sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g== + dependencies: + alphanum-sort "^1.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + +postcss-modules-extract-imports@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz#818719a1ae1da325f9832446b01136eeb493cd7e" + integrity sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ== + dependencies: + postcss "^7.0.5" + +postcss-modules-local-by-default@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz#e8a6561be914aaf3c052876377524ca90dbb7915" + integrity sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ== + dependencies: + icss-utils "^4.1.1" + postcss "^7.0.16" + postcss-selector-parser "^6.0.2" + postcss-value-parser "^4.0.0" + +postcss-modules-scope@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/postcss-modules-scope/-/postcss-modules-scope-2.1.1.tgz#33d4fc946602eb5e9355c4165d68a10727689dba" + integrity sha512-OXRUPecnHCg8b9xWvldG/jUpRIGPNRka0r4D4j0ESUU2/5IOnpsjfPPmDprM3Ih8CgZ8FXjWqaniK5v4rWt3oQ== + dependencies: + postcss "^7.0.6" + postcss-selector-parser "^6.0.0" + +postcss-modules-values@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz#5b5000d6ebae29b4255301b4a3a54574423e7f10" + integrity sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg== + dependencies: + icss-utils "^4.0.0" + postcss "^7.0.6" + +postcss-nesting@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/postcss-nesting/-/postcss-nesting-7.0.1.tgz#b50ad7b7f0173e5b5e3880c3501344703e04c052" + integrity sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg== + dependencies: + postcss "^7.0.2" + +postcss-normalize-charset@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz#8b35add3aee83a136b0471e0d59be58a50285dd4" + integrity sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g== + dependencies: + postcss "^7.0.0" + +postcss-normalize-display-values@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz#0dbe04a4ce9063d4667ed2be476bb830c825935a" + integrity sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-positions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz#05f757f84f260437378368a91f8932d4b102917f" + integrity sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA== + dependencies: + cssnano-util-get-arguments "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-repeat-style@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz#c4ebbc289f3991a028d44751cbdd11918b17910c" + integrity sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q== + dependencies: + cssnano-util-get-arguments "^4.0.0" + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-string@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz#cd44c40ab07a0c7a36dc5e99aace1eca4ec2690c" + integrity sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA== + dependencies: + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-timing-functions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz#8e009ca2a3949cdaf8ad23e6b6ab99cb5e7d28d9" + integrity sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A== + dependencies: + cssnano-util-get-match "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-unicode@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz#841bd48fdcf3019ad4baa7493a3d363b52ae1cfb" + integrity sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-url@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz#10e437f86bc7c7e58f7b9652ed878daaa95faae1" + integrity sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA== + dependencies: + is-absolute-url "^2.0.0" + normalize-url "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-normalize-whitespace@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz#bf1d4070fe4fcea87d1348e825d8cc0c5faa7d82" + integrity sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA== + dependencies: + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-ordered-values@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz#0cf75c820ec7d5c4d280189559e0b571ebac0eee" + integrity sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw== + dependencies: + cssnano-util-get-arguments "^4.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-overflow-shorthand@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz#31ecf350e9c6f6ddc250a78f0c3e111f32dd4c30" + integrity sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g== + dependencies: + postcss "^7.0.2" + +postcss-page-break@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/postcss-page-break/-/postcss-page-break-2.0.0.tgz#add52d0e0a528cabe6afee8b46e2abb277df46bf" + integrity sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ== + dependencies: + postcss "^7.0.2" + +postcss-place@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-place/-/postcss-place-4.0.1.tgz#e9f39d33d2dc584e46ee1db45adb77ca9d1dcc62" + integrity sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg== + dependencies: + postcss "^7.0.2" + postcss-values-parser "^2.0.0" + +postcss-preset-env@^6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-6.7.0.tgz#c34ddacf8f902383b35ad1e030f178f4cdf118a5" + integrity sha512-eU4/K5xzSFwUFJ8hTdTQzo2RBLbDVt83QZrAvI07TULOkmyQlnYlpwep+2yIK+K+0KlZO4BvFcleOCCcUtwchg== + dependencies: + autoprefixer "^9.6.1" + browserslist "^4.6.4" + caniuse-lite "^1.0.30000981" + css-blank-pseudo "^0.1.4" + css-has-pseudo "^0.10.0" + css-prefers-color-scheme "^3.1.1" + cssdb "^4.4.0" + postcss "^7.0.17" + postcss-attribute-case-insensitive "^4.0.1" + postcss-color-functional-notation "^2.0.1" + postcss-color-gray "^5.0.0" + postcss-color-hex-alpha "^5.0.3" + postcss-color-mod-function "^3.0.3" + postcss-color-rebeccapurple "^4.0.1" + postcss-custom-media "^7.0.8" + postcss-custom-properties "^8.0.11" + postcss-custom-selectors "^5.1.2" + postcss-dir-pseudo-class "^5.0.0" + postcss-double-position-gradients "^1.0.0" + postcss-env-function "^2.0.2" + postcss-focus-visible "^4.0.0" + postcss-focus-within "^3.0.0" + postcss-font-variant "^4.0.0" + postcss-gap-properties "^2.0.0" + postcss-image-set-function "^3.0.1" + postcss-initial "^3.0.0" + postcss-lab-function "^2.0.1" + postcss-logical "^3.0.0" + postcss-media-minmax "^4.0.0" + postcss-nesting "^7.0.0" + postcss-overflow-shorthand "^2.0.0" + postcss-page-break "^2.0.0" + postcss-place "^4.0.1" + postcss-pseudo-class-any-link "^6.0.0" + postcss-replace-overflow-wrap "^3.0.0" + postcss-selector-matches "^4.0.0" + postcss-selector-not "^4.0.0" + +postcss-pseudo-class-any-link@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz#2ed3eed393b3702879dec4a87032b210daeb04d1" + integrity sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew== + dependencies: + postcss "^7.0.2" + postcss-selector-parser "^5.0.0-rc.3" + +postcss-reduce-initial@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz#7fd42ebea5e9c814609639e2c2e84ae270ba48df" + integrity sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA== + dependencies: + browserslist "^4.0.0" + caniuse-api "^3.0.0" + has "^1.0.0" + postcss "^7.0.0" + +postcss-reduce-transforms@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz#17efa405eacc6e07be3414a5ca2d1074681d4e29" + integrity sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg== + dependencies: + cssnano-util-get-match "^4.0.0" + has "^1.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + +postcss-replace-overflow-wrap@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz#61b360ffdaedca84c7c918d2b0f0d0ea559ab01c" + integrity sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw== + dependencies: + postcss "^7.0.2" + +postcss-selector-matches@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz#71c8248f917ba2cc93037c9637ee09c64436fcff" + integrity sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww== + dependencies: + balanced-match "^1.0.0" + postcss "^7.0.2" + +postcss-selector-not@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-not/-/postcss-selector-not-4.0.0.tgz#c68ff7ba96527499e832724a2674d65603b645c0" + integrity sha512-W+bkBZRhqJaYN8XAnbbZPLWMvZD1wKTu0UxtFKdhtGjWYmxhkUneoeOhRJKdAE5V7ZTlnbHfCR+6bNwK9e1dTQ== + dependencies: + balanced-match "^1.0.0" + postcss "^7.0.2" + +postcss-selector-parser@^3.0.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-3.1.1.tgz#4f875f4afb0c96573d5cf4d74011aee250a7e865" + integrity sha1-T4dfSvsMllc9XPTXQBGu4lCn6GU= + dependencies: + dot-prop "^4.1.1" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^5.0.0-rc.3, postcss-selector-parser@^5.0.0-rc.4: + version "5.0.0" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz#249044356697b33b64f1a8f7c80922dddee7195c" + integrity sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ== + dependencies: + cssesc "^2.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz#934cf799d016c83411859e09dcecade01286ec5c" + integrity sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg== + dependencies: + cssesc "^3.0.0" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss-svgo@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-svgo/-/postcss-svgo-4.0.2.tgz#17b997bc711b333bab143aaed3b8d3d6e3d38258" + integrity sha512-C6wyjo3VwFm0QgBy+Fu7gCYOkCmgmClghO+pjcxvrcBKtiKt0uCF+hvbMO1fyv5BMImRK90SMb+dwUnfbGd+jw== + dependencies: + is-svg "^3.0.0" + postcss "^7.0.0" + postcss-value-parser "^3.0.0" + svgo "^1.0.0" + +postcss-unique-selectors@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz#9446911f3289bfd64c6d680f073c03b1f9ee4bac" + integrity sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg== + dependencies: + alphanum-sort "^1.0.0" + postcss "^7.0.0" + uniqs "^2.0.0" + +postcss-value-parser@^3.0.0, postcss-value-parser@^3.3.1: + version "3.3.1" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz#9ff822547e2893213cf1c30efa51ac5fd1ba8281" + integrity sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ== + +postcss-value-parser@^4.0.0, postcss-value-parser@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.0.2.tgz#482282c09a42706d1fc9a069b73f44ec08391dc9" + integrity sha512-LmeoohTpp/K4UiyQCwuGWlONxXamGzCMtFxLq4W1nZVGIQLYvMCJx3yAF9qyyuFpflABI9yVdtJAqbihOsCsJQ== + +postcss-values-parser@^2.0.0, postcss-values-parser@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz#da8b472d901da1e205b47bdc98637b9e9e550e5f" + integrity sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg== + dependencies: + flatten "^1.0.2" + indexes-of "^1.0.1" + uniq "^1.0.1" + +postcss@^7.0.0, postcss@^7.0.1, postcss@^7.0.14, postcss@^7.0.16, postcss@^7.0.17, postcss@^7.0.2, postcss@^7.0.23, postcss@^7.0.26, postcss@^7.0.5, postcss@^7.0.6: + version "7.0.26" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-7.0.26.tgz#5ed615cfcab35ba9bbb82414a4fa88ea10429587" + integrity sha512-IY4oRjpXWYshuTDFxMVkJDtWIk2LhsTlu8bZnbEJA4+bYT16Lvpo8Qv6EvDumhYRgzjZl489pmsY3qVgJQ08nA== + dependencies: + chalk "^2.4.2" + source-map "^0.6.1" + supports-color "^6.1.0" + +prepend-http@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/prepend-http/-/prepend-http-1.0.4.tgz#d4f4562b0ce3696e41ac52d0e002e57a635dc6dc" + integrity sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= + +pretty-error@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/pretty-error/-/pretty-error-2.1.1.tgz#5f4f87c8f91e5ae3f3ba87ab4cf5e03b1a17f1a3" + integrity sha1-X0+HyPkeWuPzuoerTPXgOxoX8aM= + dependencies: + renderkid "^2.0.1" + utila "~0.4" + +pretty-time@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pretty-time/-/pretty-time-1.1.0.tgz#ffb7429afabb8535c346a34e41873adf3d74dd0e" + integrity sha512-28iF6xPQrP8Oa6uxE6a1biz+lWeTOAPKggvjB8HAs6nVMKZwf5bG++632Dx614hIWgUPkgivRfG+a8uAXGTIbA== + +prism-react-renderer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/prism-react-renderer/-/prism-react-renderer-1.0.2.tgz#3bb9a6a42f76fc049b03266298c7068fdd4b7ea9" + integrity sha512-0++pJyRfu4v2OxI/Us/5RLui9ESDkTiLkVCtKuPZYdpB8UQWJpnJQhPrWab053XtsKW3oM0sD69uJ6N9exm1Ag== + +private@^0.1.6: + version "0.1.8" + resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" + integrity sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg== + +process-nextick-args@~2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" + integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== + +process@^0.11.10: + version "0.11.10" + resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182" + integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI= + +promise-inflight@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3" + integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM= + +prop-types@^15.5.0, prop-types@^15.6.2, prop-types@^15.7.2: + version "15.7.2" + resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" + integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== + dependencies: + loose-envify "^1.4.0" + object-assign "^4.1.1" + react-is "^16.8.1" + +property-information@^5.0.0, property-information@^5.3.0: + version "5.4.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.4.0.tgz#16e08f13f4e5c4a7be2e4ec431c01c4f8dba869a" + integrity sha512-nmMWAm/3vKFGmmOWOcdLjgq/Hlxa+hsuR/px1Lp/UGEyc5A22A6l78Shc2C0E71sPmAqglni+HrS7L7VJ7AUCA== + dependencies: + xtend "^4.0.0" + +proxy-addr@~2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.5.tgz#34cbd64a2d81f4b1fd21e76f9f06c8a45299ee34" + integrity sha512-t/7RxHXPH6cJtP0pRG6smSr9QJidhB+3kXu0KgXnbGYMgzEnUxRQ4/LDdfOwZEMyIh3/xHb8PX3t+lfL9z+YVQ== + dependencies: + forwarded "~0.1.2" + ipaddr.js "1.9.0" + +prr@~1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/prr/-/prr-1.0.1.tgz#d3fc114ba06995a45ec6893f484ceb1d78f5f476" + integrity sha1-0/wRS6BplaRexok/SEzrHXj19HY= + +psl@^1.1.28: + version "1.7.0" + resolved "https://registry.yarnpkg.com/psl/-/psl-1.7.0.tgz#f1c4c47a8ef97167dea5d6bbf4816d736e884a3c" + integrity sha512-5NsSEDv8zY70ScRnOTn7bK7eanl2MvFrOrS/R6x+dBt5g1ghnj9Zv90kO8GwT8gxcu2ANyFprnFYB85IogIJOQ== + +public-encrypt@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/public-encrypt/-/public-encrypt-4.0.3.tgz#4fcc9d77a07e48ba7527e7cbe0de33d0701331e0" + integrity sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q== + dependencies: + bn.js "^4.1.0" + browserify-rsa "^4.0.0" + create-hash "^1.1.0" + parse-asn1 "^5.0.0" + randombytes "^2.0.1" + safe-buffer "^5.1.2" + +pump@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pump/-/pump-2.0.1.tgz#12399add6e4cf7526d973cbc8b5ce2e2908b3909" + integrity sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pump@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" + integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +pumpify@^1.3.3: + version "1.5.1" + resolved "https://registry.yarnpkg.com/pumpify/-/pumpify-1.5.1.tgz#36513be246ab27570b1a374a5ce278bfd74370ce" + integrity sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ== + dependencies: + duplexify "^3.6.0" + inherits "^2.0.3" + pump "^2.0.0" + +punycode@1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.3.2.tgz#9653a036fb7c1ee42342f2325cceefea3926c48d" + integrity sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= + +punycode@^1.2.4: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha1-wNWmOycYgArY4esPpSachN1BhF4= + +punycode@^2.1.0, punycode@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +q@^1.1.2: + version "1.5.1" + resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" + integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= + +qs@6.7.0: + version "6.7.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" + integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== + +qs@~6.5.2: + version "6.5.2" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" + integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== + +query-string@^4.1.0: + version "4.3.4" + resolved "https://registry.yarnpkg.com/query-string/-/query-string-4.3.4.tgz#bbb693b9ca915c232515b228b1a02b609043dbeb" + integrity sha1-u7aTucqRXCMlFbIosaArYJBD2+s= + dependencies: + object-assign "^4.1.0" + strict-uri-encode "^1.0.0" + +querystring-es3@^0.2.0, querystring-es3@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/querystring-es3/-/querystring-es3-0.2.1.tgz#9ec61f79049875707d69414596fd907a4d711e73" + integrity sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= + +querystring@0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/querystring/-/querystring-0.2.0.tgz#b209849203bb25df820da756e747005878521620" + integrity sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= + +querystringify@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.1.1.tgz#60e5a5fd64a7f8bfa4d2ab2ed6fdf4c85bad154e" + integrity sha512-w7fLxIRCRT7U8Qu53jQnJyPkYZIaR4n5151KMfcJlO/A9397Wxb1amJvROTK6TOnp7PfoAmg/qXiNHI+08jRfA== + +randombytes@^2.0.0, randombytes@^2.0.1, randombytes@^2.0.5: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +randomfill@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/randomfill/-/randomfill-1.0.4.tgz#c92196fc86ab42be983f1bf31778224931d61458" + integrity sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw== + dependencies: + randombytes "^2.0.5" + safe-buffer "^5.1.0" + +range-parser@^1.2.1, range-parser@~1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" + integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== + +raw-body@2.4.0: + version "2.4.0" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" + integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== + dependencies: + bytes "3.1.0" + http-errors "1.7.2" + iconv-lite "0.4.24" + unpipe "1.0.0" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +react-dev-utils@^9.1.0: + version "9.1.0" + resolved "https://registry.yarnpkg.com/react-dev-utils/-/react-dev-utils-9.1.0.tgz#3ad2bb8848a32319d760d0a84c56c14bdaae5e81" + integrity sha512-X2KYF/lIGyGwP/F/oXgGDF24nxDA2KC4b7AFto+eqzc/t838gpSGiaU8trTqHXOohuLxxc5qi1eDzsl9ucPDpg== + dependencies: + "@babel/code-frame" "7.5.5" + address "1.1.2" + browserslist "4.7.0" + chalk "2.4.2" + cross-spawn "6.0.5" + detect-port-alt "1.1.6" + escape-string-regexp "1.0.5" + filesize "3.6.1" + find-up "3.0.0" + fork-ts-checker-webpack-plugin "1.5.0" + global-modules "2.0.0" + globby "8.0.2" + gzip-size "5.1.1" + immer "1.10.0" + inquirer "6.5.0" + is-root "2.1.0" + loader-utils "1.2.3" + open "^6.3.0" + pkg-up "2.0.0" + react-error-overlay "^6.0.3" + recursive-readdir "2.2.2" + shell-quote "1.7.2" + sockjs-client "1.4.0" + strip-ansi "5.2.0" + text-table "0.2.0" + +react-dom@^16.8.4: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-16.12.0.tgz#0da4b714b8d13c2038c9396b54a92baea633fe11" + integrity sha512-LMxFfAGrcS3kETtQaCkTKjMiifahaMySFDn71fZUNpPHZQEzmk/GiAeIT8JSOrHB23fnuCOMruL2a8NYlw+8Gw== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + scheduler "^0.18.0" + +react-error-overlay@^6.0.3: + version "6.0.5" + resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.5.tgz#55d59c2a3810e8b41922e0b4e5f85dcf239bd533" + integrity sha512-+DMR2k5c6BqMDSMF8hLH0vYKtKTeikiFW+fj0LClN+XZg4N9b8QUAdHC62CGWNLTi/gnuuemNcNcTFrCvK1f+A== + +react-fast-compare@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-2.0.4.tgz#e84b4d455b0fec113e0402c329352715196f81f9" + integrity sha512-suNP+J1VU1MWFKcyt7RtjiSWUjvidmQSlqu+eHslq+342xCbGTYmC0mEhPCOHxlW0CywylOC1u2DFAT+bv4dBw== + +react-helmet@^6.0.0-beta: + version "6.0.0-beta.2" + resolved "https://registry.yarnpkg.com/react-helmet/-/react-helmet-6.0.0-beta.2.tgz#8f2d464472e405e5f04efe10883c384d826258b7" + integrity sha512-rRAeil8HsddijqG2+1jeR5qY9wGQvK1zPMf+8MkiTCyhpEP/2qhAAPolEsveeAlz0xSv5C5xYypHtgCtFn0euw== + dependencies: + object-assign "^4.1.1" + prop-types "^15.7.2" + react-fast-compare "^2.0.4" + react-side-effect "^2.1.0" + +react-is@^16.6.0, react-is@^16.7.0, react-is@^16.8.1: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.12.0.tgz#2cc0fe0fba742d97fd527c42a13bec4eeb06241c" + integrity sha512-rPCkf/mWBtKc97aLL9/txD8DZdemK0vkA3JMLShjlJB3Pj3s+lpf1KaBzMfQrAmhMQB0n1cU/SUGgKKBCe837Q== + +react-loadable-ssr-addon@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/react-loadable-ssr-addon/-/react-loadable-ssr-addon-0.2.0.tgz#fbf4ebfa9cfd6eadb3c346f0459e1cee01c9cae8" + integrity sha512-gTfPaxWZa5mHKeSOE61RpoLe7hyjcJHgNa5m0ZZGV3OCkWsOKlfYgoBxXzu9ENg/ePR/kFd5H3ncF4K5eyyNTQ== + +react-loadable@^5.5.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/react-loadable/-/react-loadable-5.5.0.tgz#582251679d3da86c32aae2c8e689c59f1196d8c4" + integrity sha512-C8Aui0ZpMd4KokxRdVAm2bQtI03k2RMRNzOB+IipV3yxFTSVICv7WoUr5L9ALB5BmKO1iHgZtWM8EvYG83otdg== + dependencies: + prop-types "^15.5.0" + +react-router-config@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988" + integrity sha512-DuanZjaD8mQp1ppHjgnnUnyOlqYXZVjnov/JzFhjLEwd3Z4dYjMSnqrEzzGThH47vpCOqPPwJM2FtthLeJ8Pbg== + dependencies: + "@babel/runtime" "^7.1.2" + +react-router-dom@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.1.2.tgz#06701b834352f44d37fbb6311f870f84c76b9c18" + integrity sha512-7BPHAaIwWpZS074UKaw1FjVdZBSVWEk8IuDXdB+OkLb8vd/WRQIpA4ag9WQk61aEfQs47wHyjWUoUGGZxpQXew== + dependencies: + "@babel/runtime" "^7.1.2" + history "^4.9.0" + loose-envify "^1.3.1" + prop-types "^15.6.2" + react-router "5.1.2" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-router@5.1.2, react-router@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/react-router/-/react-router-5.1.2.tgz#6ea51d789cb36a6be1ba5f7c0d48dd9e817d3418" + integrity sha512-yjEuMFy1ONK246B+rsa0cUam5OeAQ8pyclRDgpxuSCrAlJ1qN9uZ5IgyKC7gQg0w8OM50NXHEegPh/ks9YuR2A== + dependencies: + "@babel/runtime" "^7.1.2" + history "^4.9.0" + hoist-non-react-statics "^3.1.0" + loose-envify "^1.3.1" + mini-create-react-context "^0.3.0" + path-to-regexp "^1.7.0" + prop-types "^15.6.2" + react-is "^16.6.0" + tiny-invariant "^1.0.2" + tiny-warning "^1.0.0" + +react-side-effect@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/react-side-effect/-/react-side-effect-2.1.0.tgz#1ce4a8b4445168c487ed24dab886421f74d380d3" + integrity sha512-IgmcegOSi5SNX+2Snh1vqmF0Vg/CbkycU9XZbOHJlZ6kMzTmi3yc254oB1WCkgA7OQtIAoLmcSFuHTc/tlcqXg== + +react-toggle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/react-toggle/-/react-toggle-4.1.1.tgz#2317f67bf918ea3508a96b09dd383efd9da572af" + integrity sha512-+wXlMcSpg8SmnIXauMaZiKpR+r2wp2gMUteroejp2UTSqGTVvZLN+m9EhMzFARBKEw7KpQOwzCyfzeHeAndQGw== + dependencies: + classnames "^2.2.5" + +react@^16.8.4: + version "16.12.0" + resolved "https://registry.yarnpkg.com/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83" + integrity sha512-fglqy3k5E+81pA8s+7K0/T3DBCF0ZDOher1elBFzF7O6arXJgzyu/FW+COxFvAWXJoJN9KIZbT2LXlukwphYTA== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + prop-types "^15.6.2" + +"readable-stream@1 || 2", readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable-stream@^2.0.6, readable-stream@^2.1.5, readable-stream@^2.2.2, readable-stream@^2.3.3, readable-stream@^2.3.6, readable-stream@~2.3.6: + version "2.3.7" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" + integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== + dependencies: + core-util-is "~1.0.0" + inherits "~2.0.3" + isarray "~1.0.0" + process-nextick-args "~2.0.0" + safe-buffer "~5.1.1" + string_decoder "~1.1.1" + util-deprecate "~1.0.1" + +readable-stream@^3.0.6, readable-stream@^3.1.1: + version "3.5.0" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.5.0.tgz#465d70e6d1087f6162d079cd0b5db7fbebfd1606" + integrity sha512-gSz026xs2LfxBPudDuI41V1lka8cxg64E66SGe78zJlsUofOg/yqwezdIcdfwik6B4h8LFmWPA9ef9X3FiNFLA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + +readdirp@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-2.2.1.tgz#0e87622a3325aa33e892285caf8b4e846529a525" + integrity sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ== + dependencies: + graceful-fs "^4.1.11" + micromatch "^3.1.10" + readable-stream "^2.0.2" + +readdirp@~3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.3.0.tgz#984458d13a1e42e2e9f5841b129e162f369aff17" + integrity sha512-zz0pAkSPOXXm1viEwygWIPSPkcBYjW1xU5j/JBh5t9bGCJwa6f9+BJa6VaB2g+b55yVrmXzqkyLf4xaWYM0IkQ== + dependencies: + picomatch "^2.0.7" + +rechoir@^0.6.2: + version "0.6.2" + resolved "https://registry.yarnpkg.com/rechoir/-/rechoir-0.6.2.tgz#85204b54dba82d5742e28c96756ef43af50e3384" + integrity sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q= + dependencies: + resolve "^1.1.6" + +recursive-readdir@2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/recursive-readdir/-/recursive-readdir-2.2.2.tgz#9946fb3274e1628de6e36b2f6714953b4845094f" + integrity sha512-nRCcW9Sj7NuZwa2XvH9co8NPeXUBhZP7CRKJtU+cS6PW9FpCIFoI5ib0NT1ZrbNuPoRy0ylyCaUL8Gih4LSyFg== + dependencies: + minimatch "3.0.4" + +reduce@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/reduce/-/reduce-1.0.2.tgz#0cd680ad3ffe0b060e57a5c68bdfce37168d361b" + integrity sha512-xX7Fxke/oHO5IfZSk77lvPa/7bjMh9BuCk4OOoX5XTXrM7s0Z+MkPfSDfz0q7r91BhhGSs8gii/VEN/7zhCPpQ== + dependencies: + object-keys "^1.1.0" + +regenerate-unicode-properties@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/regenerate-unicode-properties/-/regenerate-unicode-properties-8.1.0.tgz#ef51e0f0ea4ad424b77bf7cb41f3e015c70a3f0e" + integrity sha512-LGZzkgtLY79GeXLm8Dp0BVLdQlWICzBnJz/ipWUgo59qBaZ+BHtq51P2q1uVZlppMuUAT37SDk39qUbjTWB7bA== + dependencies: + regenerate "^1.4.0" + +regenerate@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/regenerate/-/regenerate-1.4.0.tgz#4a856ec4b56e4077c557589cae85e7a4c8869a11" + integrity sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg== + +regenerator-runtime@^0.13.2: + version "0.13.3" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz#7cf6a77d8f5c6f60eb73c5fc1955b2ceb01e6bf5" + integrity sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw== + +regenerator-transform@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.14.1.tgz#3b2fce4e1ab7732c08f665dfdb314749c7ddd2fb" + integrity sha512-flVuee02C3FKRISbxhXl9mGzdbWUVHubl1SMaknjxkFB1/iqpJhArQUvRxOOPEc/9tAiX0BaQ28FJH10E4isSQ== + dependencies: + private "^0.1.6" + +regex-not@^1.0.0, regex-not@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/regex-not/-/regex-not-1.0.2.tgz#1f4ece27e00b0b65e0247a6810e6a85d83a5752c" + integrity sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A== + dependencies: + extend-shallow "^3.0.2" + safe-regex "^1.1.0" + +regexp.prototype.flags@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz#7aba89b3c13a64509dabcf3ca8d9fbb9bdf5cb75" + integrity sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.0-next.1" + +regexpu-core@^4.6.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/regexpu-core/-/regexpu-core-4.6.0.tgz#2037c18b327cfce8a6fea2a4ec441f2432afb8b6" + integrity sha512-YlVaefl8P5BnFYOITTNzDvan1ulLOiXJzCNZxduTIosN17b87h3bvG9yHMoHaRuo88H4mQ06Aodj5VtYGGGiTg== + dependencies: + regenerate "^1.4.0" + regenerate-unicode-properties "^8.1.0" + regjsgen "^0.5.0" + regjsparser "^0.6.0" + unicode-match-property-ecmascript "^1.0.4" + unicode-match-property-value-ecmascript "^1.1.0" + +regjsgen@^0.5.0: + version "0.5.1" + resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.5.1.tgz#48f0bf1a5ea205196929c0d9798b42d1ed98443c" + integrity sha512-5qxzGZjDs9w4tzT3TPhCJqWdCc3RLYwy9J2NB0nm5Lz+S273lvWcpjaTGHsT1dc6Hhfq41uSEOw8wBmxrKOuyg== + +regjsparser@^0.6.0: + version "0.6.2" + resolved "https://registry.yarnpkg.com/regjsparser/-/regjsparser-0.6.2.tgz#fd62c753991467d9d1ffe0a9f67f27a529024b96" + integrity sha512-E9ghzUtoLwDekPT0DYCp+c4h+bvuUpe6rRHCTYn6eGoqj1LgKXxT6I0Il4WbjhQkOghzi/V+y03bPKvbllL93Q== + dependencies: + jsesc "~0.5.0" + +relateurl@^0.2.7: + version "0.2.7" + resolved "https://registry.yarnpkg.com/relateurl/-/relateurl-0.2.7.tgz#54dbf377e51440aca90a4cd274600d3ff2d888a9" + integrity sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= + +remark-emoji@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/remark-emoji/-/remark-emoji-2.0.2.tgz#49c134021132c192ee4cceed1988ec9b8ced7eb8" + integrity sha512-E8ZOa7Sx1YS9ivWJ8U9xpA8ldzZ4VPAfyUaKqhr1/Pr5Q8ZdQHrpDg6S+rPzMw8t89KNViB/oG9ZdJSFDrUXpA== + dependencies: + node-emoji "^1.8.1" + unist-util-visit "^1.4.0" + +remark-mdx@^1.5.5: + version "1.5.5" + resolved "https://registry.yarnpkg.com/remark-mdx/-/remark-mdx-1.5.5.tgz#7def5f778c8454b6ef7747ecb2f01376b994b884" + integrity sha512-w1XW9UzsQ6XAecV59dP8LJWn4tMftaXGwH5LEvUU5uIEJEJvHDE1jkKiPr3ow2IuhjuRfWs3b079Jtnk5qlUgQ== + dependencies: + "@babel/core" "7.8.0" + "@babel/helper-plugin-utils" "7.8.0" + "@babel/plugin-proposal-object-rest-spread" "7.8.0" + "@babel/plugin-syntax-jsx" "7.8.0" + "@mdx-js/util" "^1.5.5" + is-alphabetical "1.0.3" + remark-parse "7.0.2" + unified "8.4.2" + +remark-parse@7.0.2: + version "7.0.2" + resolved "https://registry.yarnpkg.com/remark-parse/-/remark-parse-7.0.2.tgz#41e7170d9c1d96c3d32cf1109600a9ed50dba7cf" + integrity sha512-9+my0lQS80IQkYXsMA8Sg6m9QfXYJBnXjWYN5U+kFc5/n69t+XZVXU/ZBYr3cYH8FheEGf1v87rkFDhJ8bVgMA== + dependencies: + collapse-white-space "^1.0.2" + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-whitespace-character "^1.0.0" + is-word-character "^1.0.0" + markdown-escapes "^1.0.0" + parse-entities "^1.1.0" + repeat-string "^1.5.4" + state-toggle "^1.0.0" + trim "0.0.1" + trim-trailing-lines "^1.0.0" + unherit "^1.0.4" + unist-util-remove-position "^1.0.0" + vfile-location "^2.0.0" + xtend "^4.0.1" + +remark-slug@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/remark-slug/-/remark-slug-5.1.2.tgz#715ecdef8df1226786204b1887d31ab16aa24609" + integrity sha512-DWX+Kd9iKycqyD+/B+gEFO3jjnt7Yg1O05lygYSNTe5i5PIxxxPjp5qPBDxPIzp5wreF7+1ROCwRgjEcqmzr3A== + dependencies: + github-slugger "^1.0.0" + mdast-util-to-string "^1.0.0" + unist-util-visit "^1.0.0" + +remark-squeeze-paragraphs@3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/remark-squeeze-paragraphs/-/remark-squeeze-paragraphs-3.0.4.tgz#9fe50c3bf3b572dd88754cd426ada007c0b8dc5f" + integrity sha512-Wmz5Yj9q+W1oryo8BV17JrOXZgUKVcpJ2ApE2pwnoHwhFKSk4Wp2PmFNbmJMgYSqAdFwfkoe+TSYop5Fy8wMgA== + dependencies: + mdast-squeeze-paragraphs "^3.0.0" + +remove-trailing-separator@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz#c24bce2a283adad5bc3f58e0d48249b92379d8ef" + integrity sha1-wkvOKig62tW8P1jg1IJJuSN52O8= + +renderkid@^2.0.1: + version "2.0.3" + resolved "https://registry.yarnpkg.com/renderkid/-/renderkid-2.0.3.tgz#380179c2ff5ae1365c522bf2fcfcff01c5b74149" + integrity sha512-z8CLQp7EZBPCwCnncgf9C4XAi3WR0dv+uWu/PjIyhhAb5d6IJ/QZqlHFprHeKT+59//V6BNUsLbvN8+2LarxGA== + dependencies: + css-select "^1.1.0" + dom-converter "^0.2" + htmlparser2 "^3.3.0" + strip-ansi "^3.0.0" + utila "^0.4.0" + +repeat-element@^1.1.2: + version "1.1.3" + resolved "https://registry.yarnpkg.com/repeat-element/-/repeat-element-1.1.3.tgz#782e0d825c0c5a3bb39731f84efee6b742e6b1ce" + integrity sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g== + +repeat-string@^1.5.4, repeat-string@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/repeat-string/-/repeat-string-1.6.1.tgz#8dcae470e1c88abc2d600fff4a776286da75e637" + integrity sha1-jcrkcOHIirwtYA//Sndihtp15jc= + +replace-ext@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/replace-ext/-/replace-ext-1.0.0.tgz#de63128373fcbf7c3ccfa4de5a480c45a67958eb" + integrity sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs= + +request@^2.87.0: + version "2.88.2" + resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" + integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== + dependencies: + aws-sign2 "~0.7.0" + aws4 "^1.8.0" + caseless "~0.12.0" + combined-stream "~1.0.6" + extend "~3.0.2" + forever-agent "~0.6.1" + form-data "~2.3.2" + har-validator "~5.1.3" + http-signature "~1.2.0" + is-typedarray "~1.0.0" + isstream "~0.1.2" + json-stringify-safe "~5.0.1" + mime-types "~2.1.19" + oauth-sign "~0.9.0" + performance-now "^2.1.0" + qs "~6.5.2" + safe-buffer "^5.1.2" + tough-cookie "~2.5.0" + tunnel-agent "^0.6.0" + uuid "^3.3.2" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +"require-like@>= 0.1.1": + version "0.1.2" + resolved "https://registry.yarnpkg.com/require-like/-/require-like-0.1.2.tgz#ad6f30c13becd797010c468afa775c0c0a6b47fa" + integrity sha1-rW8wwTvs15cBDEaK+ndcDAprR/o= + +require-main-filename@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-1.0.1.tgz#97f717b69d48784f5f526a6c5aa8ffdda055a4d1" + integrity sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE= + +requires-port@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" + integrity sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= + +resolve-cwd@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a" + integrity sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= + dependencies: + resolve-from "^3.0.0" + +resolve-from@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-3.0.0.tgz#b22c7af7d9d6881bc8b6e653335eebcb0a188748" + integrity sha1-six699nWiBvItuZTM17rywoYh0g= + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-pathname@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/resolve-pathname/-/resolve-pathname-3.0.0.tgz#99d02224d3cf263689becbb393bc560313025dcd" + integrity sha512-C7rARubxI8bXFNB/hqcp/4iUeIXJhJZvFPFPiSPRnhU5UPxzMFIl+2E6yY6c4k9giDJAhtV+enfA+G89N6Csng== + +resolve-url@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a" + integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= + +resolve@^1.1.6, resolve@^1.3.2, resolve@^1.8.1: + version "1.15.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" + integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== + dependencies: + path-parse "^1.0.6" + +restore-cursor@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-2.0.0.tgz#9f7ee287f82fd326d4fd162923d62129eee0dfaf" + integrity sha1-n37ih/gv0ybU/RYpI9YhKe7g368= + dependencies: + onetime "^2.0.0" + signal-exit "^3.0.2" + +ret@~0.1.10: + version "0.1.15" + resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" + integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== + +retry@^0.12.0: + version "0.12.0" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" + integrity sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= + +reusify@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rgb-regex@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/rgb-regex/-/rgb-regex-1.0.1.tgz#c0e0d6882df0e23be254a475e8edd41915feaeb1" + integrity sha1-wODWiC3w4jviVKR16O3UGRX+rrE= + +rgba-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/rgba-regex/-/rgba-regex-1.0.0.tgz#43374e2e2ca0968b0ef1523460b7d730ff22eeb3" + integrity sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= + +rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3, rimraf@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" + integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== + dependencies: + glob "^7.1.3" + +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +ripemd160@^2.0.0, ripemd160@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/ripemd160/-/ripemd160-2.0.2.tgz#a1c1a6f624751577ba5d07914cbc92850585890c" + integrity sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA== + dependencies: + hash-base "^3.0.0" + inherits "^2.0.1" + +run-async@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.3.0.tgz#0371ab4ae0bdd720d4166d7dfda64ff7a445a6c0" + integrity sha1-A3GrSuC91yDUFm19/aZP96RFpsA= + dependencies: + is-promise "^2.1.0" + +run-parallel@^1.1.9: + version "1.1.9" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.1.9.tgz#c9dd3a7cf9f4b2c4b6244e173a6ed866e61dd679" + integrity sha512-DEqnSRTDw/Tc3FXf49zedI638Z9onwUotBMiUFKmrO2sdFKIbXamXGQ3Axd4qgphxKB4kw/qP1w5kTxnfU1B9Q== + +run-queue@^1.0.0, run-queue@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/run-queue/-/run-queue-1.0.3.tgz#e848396f057d223f24386924618e25694161ec47" + integrity sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= + dependencies: + aproba "^1.1.1" + +rx@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/rx/-/rx-4.1.0.tgz#a5f13ff79ef3b740fe30aa803fb09f98805d4782" + integrity sha1-pfE/957zt0D+MKqAP7CfmIBdR4I= + +rxjs@^6.4.0: + version "6.5.4" + resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-6.5.4.tgz#e0777fe0d184cec7872df147f303572d414e211c" + integrity sha512-naMQXcgEo3csAEGvw/NydRA0fuS2nDZJiw1YUWFKU7aPPAPGZEsD4Iimit96qwCieH6y614MCLYwdkrWx7z/7Q== + dependencies: + tslib "^1.9.0" + +safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: + version "5.1.2" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" + integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== + +safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.1, safe-buffer@^5.1.2, safe-buffer@~5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" + integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== + +safe-regex@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex/-/safe-regex-1.1.0.tgz#40a3669f3b077d1e943d44629e157dd48023bf2e" + integrity sha1-QKNmnzsHfR6UPURinhV91IAjvy4= + dependencies: + ret "~0.1.10" + +"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +sax@^1.2.4, sax@~1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9" + integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw== + +scheduler@^0.18.0: + version "0.18.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.18.0.tgz#5901ad6659bc1d8f3fdaf36eb7a67b0d6746b1c4" + integrity sha512-agTSHR1Nbfi6ulI0kYNK0203joW2Y5W4po4l+v03tOoiJKpTBbxpNhWDvqc/4IcOw+KLmSiQLTasZ4cab2/UWQ== + dependencies: + loose-envify "^1.1.0" + object-assign "^4.1.1" + +schema-utils@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-1.0.0.tgz#0b79a93204d7b600d4b2850d1f66c2a34951c770" + integrity sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g== + dependencies: + ajv "^6.1.0" + ajv-errors "^1.0.0" + ajv-keywords "^3.1.0" + +schema-utils@^2.0.0, schema-utils@^2.6.0, schema-utils@^2.6.4: + version "2.6.4" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-2.6.4.tgz#a27efbf6e4e78689d91872ee3ccfa57d7bdd0f53" + integrity sha512-VNjcaUxVnEeun6B2fiiUDjXXBtD4ZSH7pdbfIu1pOFwgptDPLMo/z9jr4sUfsjFVPqDCEin/F7IYlq7/E6yDbQ== + dependencies: + ajv "^6.10.2" + ajv-keywords "^3.4.1" + +section-matter@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/section-matter/-/section-matter-1.0.0.tgz#e9041953506780ec01d59f292a19c7b850b84167" + integrity sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA== + dependencies: + extend-shallow "^2.0.1" + kind-of "^6.0.0" + +select-hose@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/select-hose/-/select-hose-2.0.0.tgz#625d8658f865af43ec962bfc376a37359a4994ca" + integrity sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= + +select@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/select/-/select-1.1.2.tgz#0e7350acdec80b1108528786ec1d4418d11b396d" + integrity sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0= + +selfsigned@^1.10.7: + version "1.10.7" + resolved "https://registry.yarnpkg.com/selfsigned/-/selfsigned-1.10.7.tgz#da5819fd049d5574f28e88a9bcc6dbc6e6f3906b" + integrity sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA== + dependencies: + node-forge "0.9.0" + +semver@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" + integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== + +semver@^5.1.0, semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.5.1, semver@^5.6.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" + integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== + +semver@^6.0.0, semver@^6.3.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +send@0.17.1: + version "0.17.1" + resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" + integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== + dependencies: + debug "2.6.9" + depd "~1.1.2" + destroy "~1.0.4" + encodeurl "~1.0.2" + escape-html "~1.0.3" + etag "~1.8.1" + fresh "0.5.2" + http-errors "~1.7.2" + mime "1.6.0" + ms "2.1.1" + on-finished "~2.3.0" + range-parser "~1.2.1" + statuses "~1.5.0" + +serialize-javascript@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-2.1.2.tgz#ecec53b0e0317bdc95ef76ab7074b7384785fa61" + integrity sha512-rs9OggEUF0V4jUSecXazOYsLfu7OGK2qIn3c7IPBiffz32XniEp/TX9Xmc9LQfK2nQ2QKHvZ2oygKUGU0lG4jQ== + +serve-index@^1.9.1: + version "1.9.1" + resolved "https://registry.yarnpkg.com/serve-index/-/serve-index-1.9.1.tgz#d3768d69b1e7d82e5ce050fff5b453bea12a9239" + integrity sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= + dependencies: + accepts "~1.3.4" + batch "0.6.1" + debug "2.6.9" + escape-html "~1.0.3" + http-errors "~1.6.2" + mime-types "~2.1.17" + parseurl "~1.3.2" + +serve-static@1.14.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" + integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== + dependencies: + encodeurl "~1.0.2" + escape-html "~1.0.3" + parseurl "~1.3.3" + send "0.17.1" + +set-blocking@^2.0.0, set-blocking@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +set-value@^2.0.0, set-value@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-value/-/set-value-2.0.1.tgz#a18d40530e6f07de4228c7defe4227af8cad005b" + integrity sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw== + dependencies: + extend-shallow "^2.0.1" + is-extendable "^0.1.1" + is-plain-object "^2.0.3" + split-string "^3.0.1" + +setimmediate@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" + integrity sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= + +setprototypeof@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" + integrity sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ== + +setprototypeof@1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" + integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== + +sha.js@^2.4.0, sha.js@^2.4.8: + version "2.4.11" + resolved "https://registry.yarnpkg.com/sha.js/-/sha.js-2.4.11.tgz#37a5cf0b81ecbc6943de109ba2960d1b26584ae7" + integrity sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ== + dependencies: + inherits "^2.0.1" + safe-buffer "^5.0.1" + +shebang-command@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-1.2.0.tgz#44aac65b695b03398968c39f363fee5deafdf1ea" + integrity sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= + dependencies: + shebang-regex "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-1.0.0.tgz#da42f49740c0b42db2ca9728571cb190c98efea3" + integrity sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +shell-quote@1.7.2: + version "1.7.2" + resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.7.2.tgz#67a7d02c76c9da24f99d20808fcaded0e0e04be2" + integrity sha512-mRz/m/JVscCrkMyPqHc/bczi3OQHkLTqXHEFu0zDhK/qfv3UcOA4SVmRCLmos4bhjr9ekVQubj/R7waKapmiQg== + +shelljs@^0.8.3: + version "0.8.3" + resolved "https://registry.yarnpkg.com/shelljs/-/shelljs-0.8.3.tgz#a7f3319520ebf09ee81275b2368adb286659b097" + integrity sha512-fc0BKlAWiLpwZljmOvAOTE/gXawtCoNrP5oaY7KIaQbbyHeQVg01pSEuEGvGh3HEdBU4baCD7wQBwADmM/7f7A== + dependencies: + glob "^7.0.0" + interpret "^1.0.0" + rechoir "^0.6.2" + +signal-exit@^3.0.0, signal-exit@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d" + integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0= + +simple-swizzle@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/simple-swizzle/-/simple-swizzle-0.2.2.tgz#a4da6b635ffcccca33f70d17cb92592de95e557a" + integrity sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= + dependencies: + is-arrayish "^0.3.1" + +sitemap@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/sitemap/-/sitemap-3.2.2.tgz#3f77c358fa97b555c879e457098e39910095c62b" + integrity sha512-TModL/WU4m2q/mQcrDgNANn0P4LwprM9MMvG4hu5zP4c6IIKs2YLTu6nXXnNr8ODW/WFtxKggiJ1EGn2W0GNmg== + dependencies: + lodash.chunk "^4.2.0" + lodash.padstart "^4.6.1" + whatwg-url "^7.0.0" + xmlbuilder "^13.0.0" + +slash@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-1.0.0.tgz#c41f2f6c39fc16d1cd17ad4b5d896114ae470d55" + integrity sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +snapdragon-node@^2.0.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/snapdragon-node/-/snapdragon-node-2.1.1.tgz#6c175f86ff14bdb0724563e8f3c1b021a286853b" + integrity sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw== + dependencies: + define-property "^1.0.0" + isobject "^3.0.0" + snapdragon-util "^3.0.1" + +snapdragon-util@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/snapdragon-util/-/snapdragon-util-3.0.1.tgz#f956479486f2acd79700693f6f7b805e45ab56e2" + integrity sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ== + dependencies: + kind-of "^3.2.0" + +snapdragon@^0.8.1: + version "0.8.2" + resolved "https://registry.yarnpkg.com/snapdragon/-/snapdragon-0.8.2.tgz#64922e7c565b0e14204ba1aa7d6964278d25182d" + integrity sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg== + dependencies: + base "^0.11.1" + debug "^2.2.0" + define-property "^0.2.5" + extend-shallow "^2.0.1" + map-cache "^0.2.2" + source-map "^0.5.6" + source-map-resolve "^0.5.0" + use "^3.1.0" + +sockjs-client@1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/sockjs-client/-/sockjs-client-1.4.0.tgz#c9f2568e19c8fd8173b4997ea3420e0bb306c7d5" + integrity sha512-5zaLyO8/nri5cua0VtOrFXBPK1jbL4+1cebT/mmKA1E1ZXOvJrII75bPu0l0k843G/+iAbhEqzyKr0w/eCCj7g== + dependencies: + debug "^3.2.5" + eventsource "^1.0.7" + faye-websocket "~0.11.1" + inherits "^2.0.3" + json3 "^3.3.2" + url-parse "^1.4.3" + +sockjs@0.3.19: + version "0.3.19" + resolved "https://registry.yarnpkg.com/sockjs/-/sockjs-0.3.19.tgz#d976bbe800af7bd20ae08598d582393508993c0d" + integrity sha512-V48klKZl8T6MzatbLlzzRNhMepEys9Y4oGFpypBFFn1gLI/QQ9HtLLyWJNbPlwGLelOVOEijUbTTJeLLI59jLw== + dependencies: + faye-websocket "^0.10.0" + uuid "^3.0.1" + +sort-keys@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-1.1.2.tgz#441b6d4d346798f1b4e49e8920adfba0e543f9ad" + integrity sha1-RBttTTRnmPG05J6JIK37oOVD+a0= + dependencies: + is-plain-obj "^1.0.0" + +source-list-map@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.1.tgz#3993bd873bfc48479cca9ea3a547835c7c154b34" + integrity sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw== + +source-map-resolve@^0.5.0: + version "0.5.3" + resolved "https://registry.yarnpkg.com/source-map-resolve/-/source-map-resolve-0.5.3.tgz#190866bece7553e1f8f267a2ee82c606b5509a1a" + integrity sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw== + dependencies: + atob "^2.1.2" + decode-uri-component "^0.2.0" + resolve-url "^0.2.1" + source-map-url "^0.4.0" + urix "^0.1.0" + +source-map-support@~0.5.12: + version "0.5.16" + resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.16.tgz#0ae069e7fe3ba7538c64c98515e35339eac5a042" + integrity sha512-efyLRJDr68D9hBBNIPWFjhpFzURh+KJykQwvMyW5UiZzYwoF6l4YMMDIJJEyFWxWCqfyxLzz6tSfUFR+kXXsVQ== + dependencies: + buffer-from "^1.0.0" + source-map "^0.6.0" + +source-map-url@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/source-map-url/-/source-map-url-0.4.0.tgz#3e935d7ddd73631b97659956d55128e87b5084a3" + integrity sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM= + +source-map@^0.5.0, source-map@^0.5.6: + version "0.5.7" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" + integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= + +source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.0, source-map@~0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +space-separated-tokens@^1.0.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" + integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== + +spdy-transport@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/spdy-transport/-/spdy-transport-3.0.0.tgz#00d4863a6400ad75df93361a1608605e5dcdcf31" + integrity sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw== + dependencies: + debug "^4.1.0" + detect-node "^2.0.4" + hpack.js "^2.1.6" + obuf "^1.1.2" + readable-stream "^3.0.6" + wbuf "^1.7.3" + +spdy@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/spdy/-/spdy-4.0.1.tgz#6f12ed1c5db7ea4f24ebb8b89ba58c87c08257f2" + integrity sha512-HeZS3PBdMA+sZSu0qwpCxl3DeALD5ASx8pAX0jZdKXSpPWbQ6SYGnlg3BBmYLx5LtiZrmkAZfErCm2oECBcioA== + dependencies: + debug "^4.1.0" + handle-thing "^2.0.0" + http-deceiver "^1.2.7" + select-hose "^2.0.0" + spdy-transport "^3.0.0" + +split-string@^3.0.1, split-string@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" + integrity sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw== + dependencies: + extend-shallow "^3.0.0" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +sshpk@^1.7.0: + version "1.16.1" + resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" + integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== + dependencies: + asn1 "~0.2.3" + assert-plus "^1.0.0" + bcrypt-pbkdf "^1.0.0" + dashdash "^1.12.0" + ecc-jsbn "~0.1.1" + getpass "^0.1.1" + jsbn "~0.1.0" + safer-buffer "^2.0.2" + tweetnacl "~0.14.0" + +ssri@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-6.0.1.tgz#2a3c41b28dd45b62b63676ecb74001265ae9edd8" + integrity sha512-3Wge10hNcT1Kur4PDFwEieXSCMCJs/7WvSACcrMYrNp+b8kDL1/0wJch5Ni2WrtwEa2IO8OsVfeKIciKCDx/QA== + dependencies: + figgy-pudding "^3.5.1" + +ssri@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/ssri/-/ssri-7.1.0.tgz#92c241bf6de82365b5c7fb4bd76e975522e1294d" + integrity sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g== + dependencies: + figgy-pudding "^3.5.1" + minipass "^3.1.1" + +stable@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/stable/-/stable-0.1.8.tgz#836eb3c8382fe2936feaf544631017ce7d47a3cf" + integrity sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w== + +stack-utils@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-1.0.2.tgz#33eba3897788558bebfc2db059dc158ec36cebb8" + integrity sha512-MTX+MeG5U994cazkjd/9KNAapsHnibjMLnfXodlkXw76JEea0UiNzrqidzo1emMwk7w5Qhc9jd4Bn9TBb1MFwA== + +state-toggle@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/state-toggle/-/state-toggle-1.0.3.tgz#e123b16a88e143139b09c6852221bc9815917dfe" + integrity sha512-d/5Z4/2iiCnHw6Xzghyhb+GcmF89bxwgXG60wjIiZaxnymbyOmI8Hk4VqHXiVVp6u2ysaskFfXg3ekCj4WNftQ== + +static-extend@^0.1.1: + version "0.1.2" + resolved "https://registry.yarnpkg.com/static-extend/-/static-extend-0.1.2.tgz#60809c39cbff55337226fd5e0b520f341f1fb5c6" + integrity sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= + dependencies: + define-property "^0.2.5" + object-copy "^0.1.0" + +"statuses@>= 1.4.0 < 2", "statuses@>= 1.5.0 < 2", statuses@~1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" + integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= + +std-env@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-2.2.1.tgz#2ffa0fdc9e2263e0004c1211966e960948a40f6b" + integrity sha512-IjYQUinA3lg5re/YMlwlfhqNRTzMZMqE+pezevdcTaHceqx8ngEi1alX9nNCk9Sc81fy1fLDeQoaCzeiW1yBOQ== + dependencies: + ci-info "^1.6.0" + +stream-browserify@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/stream-browserify/-/stream-browserify-2.0.2.tgz#87521d38a44aa7ee91ce1cd2a47df0cb49dd660b" + integrity sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg== + dependencies: + inherits "~2.0.1" + readable-stream "^2.0.2" + +stream-each@^1.1.0: + version "1.2.3" + resolved "https://registry.yarnpkg.com/stream-each/-/stream-each-1.2.3.tgz#ebe27a0c389b04fbcc233642952e10731afa9bae" + integrity sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw== + dependencies: + end-of-stream "^1.1.0" + stream-shift "^1.0.0" + +stream-http@^2.7.2: + version "2.8.3" + resolved "https://registry.yarnpkg.com/stream-http/-/stream-http-2.8.3.tgz#b2d242469288a5a27ec4fe8933acf623de6514fc" + integrity sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw== + dependencies: + builtin-status-codes "^3.0.0" + inherits "^2.0.1" + readable-stream "^2.3.6" + to-arraybuffer "^1.0.0" + xtend "^4.0.0" + +stream-shift@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.1.tgz#d7088281559ab2778424279b0877da3c392d5a3d" + integrity sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ== + +strict-uri-encode@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz#279b225df1d582b1f54e65addd4352e18faa0713" + integrity sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= + +string-width@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" + integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= + dependencies: + code-point-at "^1.0.0" + is-fullwidth-code-point "^1.0.0" + strip-ansi "^3.0.0" + +"string-width@^1.0.2 || 2", string-width@^2.0.0, string-width@^2.1.0, string-width@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.0.tgz#952182c46cc7b2c313d1596e623992bd163b72b5" + integrity sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.0" + +string.prototype.trimleft@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimleft/-/string.prototype.trimleft-2.1.1.tgz#9bdb8ac6abd6d602b17a4ed321870d2f8dcefc74" + integrity sha512-iu2AGd3PuP5Rp7x2kEZCrB2Nf41ehzh+goo8TV7z8/XDBbsvc6HQIlUl9RjkZ4oyrW1XM5UwlGl1oVEaDjg6Ag== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string.prototype.trimright@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/string.prototype.trimright/-/string.prototype.trimright-2.1.1.tgz#440314b15996c866ce8a0341894d45186200c5d9" + integrity sha512-qFvWL3/+QIgZXVmJBfpHmxLB7xsUXz6HsUmP8+5dRaC3Q7oKUv9Vo6aMCRZC1smrtyECFsIT30PqBJ1gTjAs+g== + dependencies: + define-properties "^1.1.3" + function-bind "^1.1.1" + +string_decoder@^1.0.0, string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +string_decoder@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" + integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== + dependencies: + safe-buffer "~5.1.0" + +stringify-object@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/stringify-object/-/stringify-object-3.3.0.tgz#703065aefca19300d3ce88af4f5b3956d7556629" + integrity sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw== + dependencies: + get-own-enumerable-property-symbols "^3.0.0" + is-obj "^1.0.1" + is-regexp "^1.0.0" + +strip-ansi@5.2.0, strip-ansi@^5.1.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-ansi@^3.0.0, strip-ansi@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= + dependencies: + ansi-regex "^2.0.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.0.tgz#0b1571dd7669ccd4f3e06e14ef1eed26225ae532" + integrity sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w== + dependencies: + ansi-regex "^5.0.0" + +strip-bom-string@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-bom-string/-/strip-bom-string-1.0.0.tgz#e5211e9224369fbb81d633a2f00044dc8cedad92" + integrity sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI= + +strip-eof@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/strip-eof/-/strip-eof-1.0.0.tgz#bb43ff5598a6eb05d89b59fcd129c983313606bf" + integrity sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= + +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= + +style-to-object@0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.3.0.tgz#b1b790d205991cc783801967214979ee19a76e46" + integrity sha512-CzFnRRXhzWIdItT3OmF8SQfWyahHhjq3HwcMNCNLn+N7klOOqPjMeG/4JSu77D7ypZdGvSzvkrbyeTMizz2VrA== + dependencies: + inline-style-parser "0.1.1" + +style-to-object@^0.2.1: + version "0.2.3" + resolved "https://registry.yarnpkg.com/style-to-object/-/style-to-object-0.2.3.tgz#afcf42bc03846b1e311880c55632a26ad2780bcb" + integrity sha512-1d/k4EY2N7jVLOqf2j04dTc37TPOv/hHxZmvpg8Pdh8UYydxeu/C1W1U4vD8alzf5V2Gt7rLsmkr4dxAlDm9ng== + dependencies: + inline-style-parser "0.1.1" + +stylehacks@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/stylehacks/-/stylehacks-4.0.3.tgz#6718fcaf4d1e07d8a1318690881e8d96726a71d5" + integrity sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g== + dependencies: + browserslist "^4.0.0" + postcss "^7.0.0" + postcss-selector-parser "^3.0.0" + +supports-color@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + integrity sha1-U10EXOa2Nj+kARcIRimZXp3zJMc= + +supports-color@^5.3.0: + version "5.5.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" + integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== + dependencies: + has-flag "^3.0.0" + +supports-color@^6.1.0: + version "6.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-6.1.0.tgz#0764abc69c63d5ac842dd4867e8d025e880df8f3" + integrity sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ== + dependencies: + has-flag "^3.0.0" + +supports-color@^7.0.0, supports-color@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.1.0.tgz#68e32591df73e25ad1c4b49108a2ec507962bfd1" + integrity sha512-oRSIpR8pxT1Wr2FquTNnGet79b3BWljqOuoW/h4oBhxJ/HUbX5nX6JSruTkvXDCFMwDPvsaTTbvMLKZWSy0R5g== + dependencies: + has-flag "^4.0.0" + +svgo@^1.0.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/svgo/-/svgo-1.3.2.tgz#b6dc511c063346c9e415b81e43401145b96d4167" + integrity sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw== + dependencies: + chalk "^2.4.1" + coa "^2.0.2" + css-select "^2.0.0" + css-select-base-adapter "^0.1.1" + css-tree "1.0.0-alpha.37" + csso "^4.0.2" + js-yaml "^3.13.1" + mkdirp "~0.5.1" + object.values "^1.1.0" + sax "~1.2.4" + stable "^0.1.8" + unquote "~1.1.1" + util.promisify "~1.0.0" + +tapable@^1.0.0, tapable@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-1.1.3.tgz#a1fccc06b58db61fd7a45da2da44f5f3a3e67ba2" + integrity sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA== + +tar@^4.4.2: + version "4.4.13" + resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" + integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== + dependencies: + chownr "^1.1.1" + fs-minipass "^1.2.5" + minipass "^2.8.6" + minizlib "^1.2.1" + mkdirp "^0.5.0" + safe-buffer "^5.1.2" + yallist "^3.0.3" + +terser-webpack-plugin@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-1.4.3.tgz#5ecaf2dbdc5fb99745fd06791f46fc9ddb1c9a7c" + integrity sha512-QMxecFz/gHQwteWwSo5nTc6UaICqN1bMedC5sMtUc7y3Ha3Q8y6ZO0iCR8pq4RJC8Hjf0FEPEHZqcMB/+DFCrA== + dependencies: + cacache "^12.0.2" + find-cache-dir "^2.1.0" + is-wsl "^1.1.0" + schema-utils "^1.0.0" + serialize-javascript "^2.1.2" + source-map "^0.6.1" + terser "^4.1.2" + webpack-sources "^1.4.0" + worker-farm "^1.7.0" + +terser-webpack-plugin@^2.2.1: + version "2.3.4" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-2.3.4.tgz#ac045703bd8da0936ce910d8fb6350d0e1dee5fe" + integrity sha512-Nv96Nws2R2nrFOpbzF6IxRDpIkkIfmhvOws+IqMvYdFLO7o6wAILWFKONFgaYy8+T4LVz77DQW0f7wOeDEAjrg== + dependencies: + cacache "^13.0.1" + find-cache-dir "^3.2.0" + jest-worker "^25.1.0" + p-limit "^2.2.2" + schema-utils "^2.6.4" + serialize-javascript "^2.1.2" + source-map "^0.6.1" + terser "^4.4.3" + webpack-sources "^1.4.3" + +terser@^4.1.2, terser@^4.3.9, terser@^4.4.3: + version "4.6.3" + resolved "https://registry.yarnpkg.com/terser/-/terser-4.6.3.tgz#e33aa42461ced5238d352d2df2a67f21921f8d87" + integrity sha512-Lw+ieAXmY69d09IIc/yqeBqXpEQIpDGZqT34ui1QWXIUpR2RjbqEkT8X7Lgex19hslSqcWM5iMN2kM11eMsESQ== + dependencies: + commander "^2.20.0" + source-map "~0.6.1" + source-map-support "~0.5.12" + +text-table@0.2.0, text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= + +through2@^2.0.0: + version "2.0.5" + resolved "https://registry.yarnpkg.com/through2/-/through2-2.0.5.tgz#01c1e39eb31d07cb7d03a96a70823260b23132cd" + integrity sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ== + dependencies: + readable-stream "~2.3.6" + xtend "~4.0.1" + +through@^2.3.6, through@~2.3.4: + version "2.3.8" + resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" + integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= + +thunky@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/thunky/-/thunky-1.1.0.tgz#5abaf714a9405db0504732bbccd2cedd9ef9537d" + integrity sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA== + +timers-browserify@^2.0.4: + version "2.0.11" + resolved "https://registry.yarnpkg.com/timers-browserify/-/timers-browserify-2.0.11.tgz#800b1f3eee272e5bc53ee465a04d0e804c31211f" + integrity sha512-60aV6sgJ5YEbzUdn9c8kYGIqOubPoUdqQCul3SBAsRCZ40s6Y5cMcrW4dt3/k/EsbLVJNl9n6Vz3fTc+k2GeKQ== + dependencies: + setimmediate "^1.0.4" + +timsort@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/timsort/-/timsort-0.3.0.tgz#405411a8e7e6339fe64db9a234de11dc31e02bd4" + integrity sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= + +tiny-emitter@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423" + integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q== + +tiny-invariant@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/tiny-invariant/-/tiny-invariant-1.1.0.tgz#634c5f8efdc27714b7f386c35e6760991d230875" + integrity sha512-ytxQvrb1cPc9WBEI/HSeYYoGD0kWnGEOR8RY6KomWLBVhqz0RgTwVO9dLrGz7dC+nN9llyI7OKAgRq8Vq4ZBSw== + +tiny-warning@^1.0.0, tiny-warning@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" + integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-arraybuffer@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz#7d229b1fcc637e466ca081180836a7aabff83f43" + integrity sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= + +to-factory@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/to-factory/-/to-factory-1.0.0.tgz#8738af8bd97120ad1d4047972ada5563bf9479b1" + integrity sha1-hzivi9lxIK0dQEeXKtpVY7+UebE= + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= + +to-object-path@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/to-object-path/-/to-object-path-0.3.0.tgz#297588b7b0e7e0ac08e04e672f85c1f4999e17af" + integrity sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= + dependencies: + kind-of "^3.0.2" + +to-regex-range@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-2.1.1.tgz#7c80c17b9dfebe599e27367e0d4dd5590141db38" + integrity sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= + dependencies: + is-number "^3.0.0" + repeat-string "^1.6.1" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +to-regex@^3.0.1, to-regex@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/to-regex/-/to-regex-3.0.2.tgz#13cfdd9b336552f30b51f33a8ae1b42a7a7599ce" + integrity sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw== + dependencies: + define-property "^2.0.2" + extend-shallow "^3.0.2" + regex-not "^1.0.2" + safe-regex "^1.1.0" + +toidentifier@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" + integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== + +tough-cookie@~2.5.0: + version "2.5.0" + resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" + integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== + dependencies: + psl "^1.1.28" + punycode "^2.1.1" + +tr46@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tr46/-/tr46-1.0.1.tgz#a8b13fd6bfd2489519674ccde55ba3693b706d09" + integrity sha1-qLE/1r/SSJUZZ0zN5VujaTtwbQk= + dependencies: + punycode "^2.1.0" + +trim-lines@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/trim-lines/-/trim-lines-1.1.3.tgz#839514be82428fd9e7ec89e35081afe8f6f93115" + integrity sha512-E0ZosSWYK2mkSu+KEtQ9/KqarVjA9HztOSX+9FDdNacRAq29RRV6ZQNgob3iuW8Htar9vAfEa6yyt5qBAHZDBA== + +trim-trailing-lines@^1.0.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/trim-trailing-lines/-/trim-trailing-lines-1.1.3.tgz#7f0739881ff76657b7776e10874128004b625a94" + integrity sha512-4ku0mmjXifQcTVfYDfR5lpgV7zVqPg6zV9rdZmwOPqq0+Zq19xDqEgagqVbc4pOOShbncuAOIs59R3+3gcF3ZA== + +trim@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/trim/-/trim-0.0.1.tgz#5858547f6b290757ee95cccc666fb50084c460dd" + integrity sha1-WFhUf2spB1fulczMZm+1AITEYN0= + +trough@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.5.tgz#b8b639cefad7d0bb2abd37d433ff8293efa5f406" + integrity sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA== + +tryer@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" + integrity sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA== + +tslib@^1.9.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.10.0.tgz#c3c19f95973fb0a62973fb09d90d961ee43e5c8a" + integrity sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ== + +tty-browserify@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/tty-browserify/-/tty-browserify-0.0.0.tgz#a157ba402da24e9bf957f9aa69d524eed42901a6" + integrity sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= + +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= + dependencies: + safe-buffer "^5.0.1" + +tweetnacl@^0.14.3, tweetnacl@~0.14.0: + version "0.14.5" + resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" + integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= + +type-fest@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +type-is@~1.6.17, type-is@~1.6.18: + version "1.6.18" + resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" + integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== + dependencies: + media-typer "0.3.0" + mime-types "~2.1.24" + +typedarray@^0.0.6: + version "0.0.6" + resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" + integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= + +unherit@^1.0.4: + version "1.1.3" + resolved "https://registry.yarnpkg.com/unherit/-/unherit-1.1.3.tgz#6c9b503f2b41b262330c80e91c8614abdaa69c22" + integrity sha512-Ft16BJcnapDKp0+J/rqFC3Rrk6Y/Ng4nzsC028k2jdDII/rdZ7Wd3pPT/6+vIIxRagwRc9K0IUX0Ra4fKvw+WQ== + dependencies: + inherits "^2.0.0" + xtend "^4.0.0" + +unicode-canonical-property-names-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz#2619800c4c825800efdd8343af7dd9933cbe2818" + integrity sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ== + +unicode-match-property-ecmascript@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz#8ed2a32569961bce9227d09cd3ffbb8fed5f020c" + integrity sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg== + dependencies: + unicode-canonical-property-names-ecmascript "^1.0.4" + unicode-property-aliases-ecmascript "^1.0.4" + +unicode-match-property-value-ecmascript@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.1.0.tgz#5b4b426e08d13a80365e0d657ac7a6c1ec46a277" + integrity sha512-hDTHvaBk3RmFzvSl0UVrUmC3PuW9wKVnpoUDYH0JDkSIovzw+J5viQmeYHxVSBptubnr7PbH2e0fnpDRQnQl5g== + +unicode-property-aliases-ecmascript@^1.0.4: + version "1.0.5" + resolved "https://registry.yarnpkg.com/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.0.5.tgz#a9cc6cc7ce63a0a3023fc99e341b94431d405a57" + integrity sha512-L5RAqCfXqAwR3RriF8pM0lU0w4Ryf/GgzONwi6KnL1taJQa7x1TCxdJnILX59WIGOwR57IVxn7Nej0fz1Ny6fw== + +unified@8.4.2: + version "8.4.2" + resolved "https://registry.yarnpkg.com/unified/-/unified-8.4.2.tgz#13ad58b4a437faa2751a4a4c6a16f680c500fff1" + integrity sha512-JCrmN13jI4+h9UAyKEoGcDZV+i1E7BLFuG7OsaDvTXI5P0qhHX+vZO/kOhz9jn8HGENDKbwSeB0nVOg4gVStGA== + dependencies: + bail "^1.0.0" + extend "^3.0.0" + is-plain-obj "^2.0.0" + trough "^1.0.0" + vfile "^4.0.0" + +union-value@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" + integrity sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg== + dependencies: + arr-union "^3.1.0" + get-value "^2.0.6" + is-extendable "^0.1.1" + set-value "^2.0.1" + +uniq@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/uniq/-/uniq-1.0.1.tgz#b31c5ae8254844a3a8281541ce2b04b865a734ff" + integrity sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= + +uniqs@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/uniqs/-/uniqs-2.0.0.tgz#ffede4b36b25290696e6e165d4a59edb998e6b02" + integrity sha1-/+3ks2slKQaW5uFl1KWe25mOawI= + +unique-filename@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unique-filename/-/unique-filename-1.1.1.tgz#1d69769369ada0583103a1e6ae87681b56573230" + integrity sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ== + dependencies: + unique-slug "^2.0.0" + +unique-slug@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unique-slug/-/unique-slug-2.0.2.tgz#baabce91083fc64e945b0f3ad613e264f7cd4e6c" + integrity sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w== + dependencies: + imurmurhash "^0.1.4" + +unist-builder@1.0.4, unist-builder@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/unist-builder/-/unist-builder-1.0.4.tgz#e1808aed30bd72adc3607f25afecebef4dd59e17" + integrity sha512-v6xbUPP7ILrT15fHGrNyHc1Xda8H3xVhP7/HAIotHOhVPjH5dCXA097C3Rry1Q2O+HbOLCao4hfPB+EYEjHgVg== + dependencies: + object-assign "^4.1.0" + +unist-util-generated@^1.1.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/unist-util-generated/-/unist-util-generated-1.1.5.tgz#1e903e68467931ebfaea386dae9ea253628acd42" + integrity sha512-1TC+NxQa4N9pNdayCYA1EGUOCAO0Le3fVp7Jzns6lnua/mYgwHo0tz5WUAfrdpNch1RZLHc61VZ1SDgrtNXLSw== + +unist-util-is@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-3.0.0.tgz#d9e84381c2468e82629e4a5be9d7d05a2dd324cd" + integrity sha512-sVZZX3+kspVNmLWBPAB6r+7D9ZgAFPNWm66f7YNb420RlQSbn+n8rG8dGZSkrER7ZIXGQYNm5pqC3v3HopH24A== + +unist-util-is@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/unist-util-is/-/unist-util-is-4.0.1.tgz#ae3e39b9ad1b138c8e3b9d2f4658ad0031be4610" + integrity sha512-7NYjErP4LJtkEptPR22wO5RsCPnHZZrop7t2SoQzjvpFedCFer4WW8ujj9GI5DkUX7yVcffXLjoURf6h2QUv6Q== + +unist-util-position@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/unist-util-position/-/unist-util-position-3.0.4.tgz#5872be7aec38629b971fdb758051f78817b0040a" + integrity sha512-tWvIbV8goayTjobxDIr4zVTyG+Q7ragMSMeKC3xnPl9xzIc0+she8mxXLM3JVNDDsfARPbCd3XdzkyLdo7fF3g== + +unist-util-remove-position@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/unist-util-remove-position/-/unist-util-remove-position-1.1.4.tgz#ec037348b6102c897703eee6d0294ca4755a2020" + integrity sha512-tLqd653ArxJIPnKII6LMZwH+mb5q+n/GtXQZo6S6csPRs5zB0u79Yw8ouR3wTw8wxvdJFhpP6Y7jorWdCgLO0A== + dependencies: + unist-util-visit "^1.1.0" + +unist-util-remove@^1.0.0: + version "1.0.3" + resolved "https://registry.yarnpkg.com/unist-util-remove/-/unist-util-remove-1.0.3.tgz#58ec193dfa84b52d5a055ffbc58e5444eb8031a3" + integrity sha512-mB6nCHCQK0pQffUAcCVmKgIWzG/AXs/V8qpS8K72tMPtOSCMSjDeMc5yN+Ye8rB0FhcE+JvW++o1xRNc0R+++g== + dependencies: + unist-util-is "^3.0.0" + +unist-util-stringify-position@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/unist-util-stringify-position/-/unist-util-stringify-position-2.0.2.tgz#5a3866e7138d55974b640ec69a94bc19e0f3fa12" + integrity sha512-nK5n8OGhZ7ZgUwoUbL8uiVRwAbZyzBsB/Ddrlbu6jwwubFza4oe15KlyEaLNMXQW1svOQq4xesUeqA85YrIUQA== + dependencies: + "@types/unist" "^2.0.2" + +unist-util-visit-parents@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz#25e43e55312166f3348cae6743588781d112c1e9" + integrity sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g== + dependencies: + unist-util-is "^3.0.0" + +unist-util-visit-parents@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/unist-util-visit-parents/-/unist-util-visit-parents-3.0.1.tgz#666883dc8684c6eec04a7e9781cdcd8b4888319f" + integrity sha512-umEOTkm6/y1gIqPrqet55mYqlvGXCia/v1FSc5AveLAI7jFmOAIbqiwcHcviLcusAkEQt1bq2hixCKO9ltMb2Q== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + +unist-util-visit@2.0.1, unist-util-visit@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-2.0.1.tgz#b4e1c1cb414250c6b3cb386b8e461d79312108ae" + integrity sha512-bEDa5S/O8WRDeI1mLaMoKuFFi89AjF+UAoMNxO+bbVdo06q+53Vhq4iiv1PenL6Rx1ZxIpXIzqZoc5HD2I1oMA== + dependencies: + "@types/unist" "^2.0.0" + unist-util-is "^4.0.0" + unist-util-visit-parents "^3.0.0" + +unist-util-visit@^1.0.0, unist-util-visit@^1.1.0, unist-util-visit@^1.4.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/unist-util-visit/-/unist-util-visit-1.4.1.tgz#4724aaa8486e6ee6e26d7ff3c8685960d560b1e3" + integrity sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw== + dependencies: + unist-util-visit-parents "^2.0.0" + +universalify@^0.1.0: + version "0.1.2" + resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.1.2.tgz#b646f69be3942dabcecc9d6639c80dc105efaa66" + integrity sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg== + +unpipe@1.0.0, unpipe@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" + integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= + +unquote@~1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/unquote/-/unquote-1.1.1.tgz#8fded7324ec6e88a0ff8b905e7c098cdc086d544" + integrity sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= + +unset-value@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/unset-value/-/unset-value-1.0.0.tgz#8376873f7d2335179ffb1e6fc3a8ed0dfc8ab559" + integrity sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= + dependencies: + has-value "^0.3.1" + isobject "^3.0.0" + +upath@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/upath/-/upath-1.2.0.tgz#8f66dbcd55a883acdae4408af8b035a5044c1894" + integrity sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg== + +upper-case@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/upper-case/-/upper-case-1.1.3.tgz#f6b4501c2ec4cdd26ba78be7222961de77621598" + integrity sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= + +uri-js@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" + integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== + dependencies: + punycode "^2.1.0" + +urix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" + integrity sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= + +url-parse@^1.4.3: + version "1.4.7" + resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.4.7.tgz#a8a83535e8c00a316e403a5db4ac1b9b853ae278" + integrity sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg== + dependencies: + querystringify "^2.1.1" + requires-port "^1.0.0" + +url@^0.11.0: + version "0.11.0" + resolved "https://registry.yarnpkg.com/url/-/url-0.11.0.tgz#3838e97cfc60521eb73c525a8e55bfdd9e2e28f1" + integrity sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= + dependencies: + punycode "1.3.2" + querystring "0.2.0" + +use@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/use/-/use-3.1.1.tgz#d50c8cac79a19fbc20f2911f56eb973f4e10070f" + integrity sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ== + +util-deprecate@^1.0.1, util-deprecate@~1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= + +util.promisify@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.0.tgz#440f7165a459c9a16dc145eb8e72f35687097030" + integrity sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA== + dependencies: + define-properties "^1.1.2" + object.getownpropertydescriptors "^2.0.3" + +util.promisify@~1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/util.promisify/-/util.promisify-1.0.1.tgz#6baf7774b80eeb0f7520d8b81d07982a59abbaee" + integrity sha512-g9JpC/3He3bm38zsLupWryXHoEcS22YHthuPQSJdMy6KNrzIRzWqcsHzD/WUnqe45whVou4VIsPew37DoXWNrA== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.2" + has-symbols "^1.0.1" + object.getownpropertydescriptors "^2.1.0" + +util@0.10.3: + version "0.10.3" + resolved "https://registry.yarnpkg.com/util/-/util-0.10.3.tgz#7afb1afe50805246489e3db7fe0ed379336ac0f9" + integrity sha1-evsa/lCAUkZInj23/g7TeTNqwPk= + dependencies: + inherits "2.0.1" + +util@^0.11.0: + version "0.11.1" + resolved "https://registry.yarnpkg.com/util/-/util-0.11.1.tgz#3236733720ec64bb27f6e26f421aaa2e1b588d61" + integrity sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ== + dependencies: + inherits "2.0.3" + +utila@^0.4.0, utila@~0.4: + version "0.4.0" + resolved "https://registry.yarnpkg.com/utila/-/utila-0.4.0.tgz#8a16a05d445657a3aea5eecc5b12a4fa5379772c" + integrity sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= + +utils-merge@1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" + integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= + +uuid@^3.0.1, uuid@^3.3.2: + version "3.4.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" + integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== + +value-equal@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c" + integrity sha512-NOJ6JZCAWr0zlxZt+xqCHNTEKOsrks2HQd4MqhP1qy4z1SkbEP467eNx6TgDKXMvUOb+OENfJCZwM+16n7fRfw== + +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= + +vendors@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/vendors/-/vendors-1.0.4.tgz#e2b800a53e7a29b93506c3cf41100d16c4c4ad8e" + integrity sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w== + +verror@1.10.0: + version "1.10.0" + resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" + integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= + dependencies: + assert-plus "^1.0.0" + core-util-is "1.0.2" + extsprintf "^1.2.0" + +vfile-location@^2.0.0: + version "2.0.6" + resolved "https://registry.yarnpkg.com/vfile-location/-/vfile-location-2.0.6.tgz#8a274f39411b8719ea5728802e10d9e0dff1519e" + integrity sha512-sSFdyCP3G6Ka0CEmN83A2YCMKIieHx0EDaj5IDP4g1pa5ZJ4FJDvpO0WODLxo4LUX4oe52gmSCK7Jw4SBghqxA== + +vfile-message@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/vfile-message/-/vfile-message-2.0.2.tgz#75ba05090ec758fa8420f2c11ce049bcddd8cf3e" + integrity sha512-gNV2Y2fDvDOOqq8bEe7cF3DXU6QgV4uA9zMR2P8tix11l1r7zju3zry3wZ8sx+BEfuO6WQ7z2QzfWTvqHQiwsA== + dependencies: + "@types/unist" "^2.0.0" + unist-util-stringify-position "^2.0.0" + +vfile@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/vfile/-/vfile-4.0.2.tgz#71af004d4a710b0e6be99c894655bc56126d5d56" + integrity sha512-yhoTU5cDMSsaeaMfJ5g0bUKYkYmZhAh9fn9TZicxqn+Cw4Z439il2v3oT9S0yjlpqlI74aFOQCt3nOV+pxzlkw== + dependencies: + "@types/unist" "^2.0.0" + is-buffer "^2.0.0" + replace-ext "1.0.0" + unist-util-stringify-position "^2.0.0" + vfile-message "^2.0.0" + +vm-browserify@^1.0.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" + integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== + +wait-file@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/wait-file/-/wait-file-1.0.5.tgz#377f48795f1765046a41bb0671c142ef8e509ae6" + integrity sha512-udLpJY/eOxlrMm3+XD1RLuF2oT9B7J7wiyR5/9xrvQymS6YR6trWvVhzOldHrVbLwyiRmLj9fcvsjzpSXeZHkw== + dependencies: + "@hapi/joi" "^15.1.0" + fs-extra "^8.1.0" + rx "^4.1.0" + +watchpack@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-1.6.0.tgz#4bc12c2ebe8aa277a71f1d3f14d685c7b446cd00" + integrity sha512-i6dHe3EyLjMmDlU1/bGQpEw25XSjkJULPuAVKCbNRefQVq48yXKUpwg538F7AZTf9kyr57zj++pQFltUa5H7yA== + dependencies: + chokidar "^2.0.2" + graceful-fs "^4.1.2" + neo-async "^2.5.0" + +wbuf@^1.1.0, wbuf@^1.7.3: + version "1.7.3" + resolved "https://registry.yarnpkg.com/wbuf/-/wbuf-1.7.3.tgz#c1d8d149316d3ea852848895cb6a0bfe887b87df" + integrity sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA== + dependencies: + minimalistic-assert "^1.0.0" + +web-namespaces@^1.0.0, web-namespaces@^1.1.2: + version "1.1.4" + resolved "https://registry.yarnpkg.com/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" + integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== + +webidl-conversions@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" + integrity sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg== + +webpack-bundle-analyzer@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.6.0.tgz#39b3a8f829ca044682bc6f9e011c95deb554aefd" + integrity sha512-orUfvVYEfBMDXgEKAKVvab5iQ2wXneIEorGNsyuOyVYpjYrI7CUOhhXNDd3huMwQ3vNNWWlGP+hzflMFYNzi2g== + dependencies: + acorn "^6.0.7" + acorn-walk "^6.1.1" + bfj "^6.1.1" + chalk "^2.4.1" + commander "^2.18.0" + ejs "^2.6.1" + express "^4.16.3" + filesize "^3.6.1" + gzip-size "^5.0.0" + lodash "^4.17.15" + mkdirp "^0.5.1" + opener "^1.5.1" + ws "^6.0.0" + +webpack-dev-middleware@^3.7.2: + version "3.7.2" + resolved "https://registry.yarnpkg.com/webpack-dev-middleware/-/webpack-dev-middleware-3.7.2.tgz#0019c3db716e3fa5cecbf64f2ab88a74bab331f3" + integrity sha512-1xC42LxbYoqLNAhV6YzTYacicgMZQTqRd27Sim9wn5hJrX3I5nxYy1SxSd4+gjUFsz1dQFj+yEe6zEVmSkeJjw== + dependencies: + memory-fs "^0.4.1" + mime "^2.4.4" + mkdirp "^0.5.1" + range-parser "^1.2.1" + webpack-log "^2.0.0" + +webpack-dev-server@^3.9.0: + version "3.10.3" + resolved "https://registry.yarnpkg.com/webpack-dev-server/-/webpack-dev-server-3.10.3.tgz#f35945036813e57ef582c2420ef7b470e14d3af0" + integrity sha512-e4nWev8YzEVNdOMcNzNeCN947sWJNd43E5XvsJzbAL08kGc2frm1tQ32hTJslRS+H65LCb/AaUCYU7fjHCpDeQ== + dependencies: + ansi-html "0.0.7" + bonjour "^3.5.0" + chokidar "^2.1.8" + compression "^1.7.4" + connect-history-api-fallback "^1.6.0" + debug "^4.1.1" + del "^4.1.1" + express "^4.17.1" + html-entities "^1.2.1" + http-proxy-middleware "0.19.1" + import-local "^2.0.0" + internal-ip "^4.3.0" + ip "^1.1.5" + is-absolute-url "^3.0.3" + killable "^1.0.1" + loglevel "^1.6.6" + opn "^5.5.0" + p-retry "^3.0.1" + portfinder "^1.0.25" + schema-utils "^1.0.0" + selfsigned "^1.10.7" + semver "^6.3.0" + serve-index "^1.9.1" + sockjs "0.3.19" + sockjs-client "1.4.0" + spdy "^4.0.1" + strip-ansi "^3.0.1" + supports-color "^6.1.0" + url "^0.11.0" + webpack-dev-middleware "^3.7.2" + webpack-log "^2.0.0" + ws "^6.2.1" + yargs "12.0.5" + +webpack-log@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/webpack-log/-/webpack-log-2.0.0.tgz#5b7928e0637593f119d32f6227c1e0ac31e1b47f" + integrity sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg== + dependencies: + ansi-colors "^3.0.0" + uuid "^3.3.2" + +webpack-merge@^4.2.2: + version "4.2.2" + resolved "https://registry.yarnpkg.com/webpack-merge/-/webpack-merge-4.2.2.tgz#a27c52ea783d1398afd2087f547d7b9d2f43634d" + integrity sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g== + dependencies: + lodash "^4.17.15" + +webpack-sources@^1.1.0, webpack-sources@^1.4.0, webpack-sources@^1.4.1, webpack-sources@^1.4.3: + version "1.4.3" + resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-1.4.3.tgz#eedd8ec0b928fbf1cbfe994e22d2d890f330a933" + integrity sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ== + dependencies: + source-list-map "^2.0.0" + source-map "~0.6.1" + +webpack@^4.41.2: + version "4.41.6" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-4.41.6.tgz#12f2f804bf6542ef166755050d4afbc8f66ba7e1" + integrity sha512-yxXfV0Zv9WMGRD+QexkZzmGIh54bsvEs+9aRWxnN8erLWEOehAKUTeNBoUbA6HPEZPlRo7KDi2ZcNveoZgK9MA== + dependencies: + "@webassemblyjs/ast" "1.8.5" + "@webassemblyjs/helper-module-context" "1.8.5" + "@webassemblyjs/wasm-edit" "1.8.5" + "@webassemblyjs/wasm-parser" "1.8.5" + acorn "^6.2.1" + ajv "^6.10.2" + ajv-keywords "^3.4.1" + chrome-trace-event "^1.0.2" + enhanced-resolve "^4.1.0" + eslint-scope "^4.0.3" + json-parse-better-errors "^1.0.2" + loader-runner "^2.4.0" + loader-utils "^1.2.3" + memory-fs "^0.4.1" + micromatch "^3.1.10" + mkdirp "^0.5.1" + neo-async "^2.6.1" + node-libs-browser "^2.2.1" + schema-utils "^1.0.0" + tapable "^1.1.3" + terser-webpack-plugin "^1.4.3" + watchpack "^1.6.0" + webpack-sources "^1.4.1" + +webpackbar@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/webpackbar/-/webpackbar-4.0.0.tgz#ee7a87f16077505b5720551af413c8ecd5b1f780" + integrity sha512-k1qRoSL/3BVuINzngj09nIwreD8wxV4grcuhHTD8VJgUbGcy8lQSPqv+bM00B7F+PffwIsQ8ISd4mIwRbr23eQ== + dependencies: + ansi-escapes "^4.2.1" + chalk "^2.4.2" + consola "^2.10.0" + figures "^3.0.0" + pretty-time "^1.1.0" + std-env "^2.2.1" + text-table "^0.2.0" + wrap-ansi "^6.0.0" + +websocket-driver@>=0.5.1: + version "0.7.3" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.3.tgz#a2d4e0d4f4f116f1e6297eba58b05d430100e9f9" + integrity sha512-bpxWlvbbB459Mlipc5GBzzZwhoZgGEZLuqPaR0INBGnPAY1vdBX6hPnoFXiw+3yWxDuHyQjO2oXTMyS8A5haFg== + dependencies: + http-parser-js ">=0.4.0 <0.4.11" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.3" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.3.tgz#5d2ff22977003ec687a4b87073dfbbac146ccf29" + integrity sha512-nqHUnMXmBzT0w570r2JpJxfiSD1IzoI+HGVdd3aZ0yNi3ngvQ4jv1dtHt5VGxfI2yj5yqImPhOK4vmIh2xMbGg== + +whatwg-url@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" + integrity sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg== + dependencies: + lodash.sortby "^4.7.0" + tr46 "^1.0.1" + webidl-conversions "^4.0.2" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@^1.2.9, which@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" + integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== + dependencies: + isexe "^2.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@^1.1.0: + version "1.1.3" + resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +worker-farm@^1.7.0: + version "1.7.0" + resolved "https://registry.yarnpkg.com/worker-farm/-/worker-farm-1.7.0.tgz#26a94c5391bbca926152002f69b84a4bf772e5a8" + integrity sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw== + dependencies: + errno "~0.1.7" + +worker-rpc@^0.1.0: + version "0.1.1" + resolved "https://registry.yarnpkg.com/worker-rpc/-/worker-rpc-0.1.1.tgz#cb565bd6d7071a8f16660686051e969ad32f54d5" + integrity sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg== + dependencies: + microevent.ts "~0.1.1" + +wrap-ansi@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" + integrity sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU= + dependencies: + string-width "^1.0.1" + strip-ansi "^3.0.1" + +wrap-ansi@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +ws@^6.0.0, ws@^6.2.1: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ws/-/ws-6.2.1.tgz#442fdf0a47ed64f59b6a5d8ff130f4748ed524fb" + integrity sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA== + dependencies: + async-limiter "~1.0.0" + +xml-js@^1.6.11: + version "1.6.11" + resolved "https://registry.yarnpkg.com/xml-js/-/xml-js-1.6.11.tgz#927d2f6947f7f1c19a316dd8eea3614e8b18f8e9" + integrity sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g== + dependencies: + sax "^1.2.4" + +xmlbuilder@^13.0.0: + version "13.0.2" + resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-13.0.2.tgz#02ae33614b6a047d1c32b5389c1fdacb2bce47a7" + integrity sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ== + +xtend@^4.0.0, xtend@^4.0.1, xtend@~4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +"y18n@^3.2.1 || ^4.0.0", y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yallist@^3.0.0, yallist@^3.0.2, yallist@^3.0.3: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^11.1.1: + version "11.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-11.1.1.tgz#879a0865973bca9f6bab5cbdf3b1c67ec7d3bcf4" + integrity sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs@12.0.5: + version "12.0.5" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-12.0.5.tgz#05f5997b609647b64f66b81e3b4b10a368e7ad13" + integrity sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw== + dependencies: + cliui "^4.0.0" + decamelize "^1.2.0" + find-up "^3.0.0" + get-caller-file "^1.0.1" + os-locale "^3.0.0" + require-directory "^2.1.1" + require-main-filename "^1.0.1" + set-blocking "^2.0.0" + string-width "^2.0.0" + which-module "^2.0.0" + y18n "^3.2.1 || ^4.0.0" + yargs-parser "^11.1.1" + +zepto@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/zepto/-/zepto-1.2.0.tgz#e127bd9e66fd846be5eab48c1394882f7c0e4f98" + integrity sha1-4Se9nmb9hGvl6rSME5SIL3wOT5g= + +zwitch@^1.0.0: + version "1.0.5" + resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-1.0.5.tgz#d11d7381ffed16b742f6af7b3f223d5cd9fe9920" + integrity sha512-V50KMwwzqJV0NpZIZFwfOD5/lyny3WlSzRiXgA0G7VUnRlqttta1L6UQIHzd6EuBY/cHGfwTIck7w1yH6Q5zUw==