From 0ffe2b4edf7159b615fd235c978d9b888b3055f0 Mon Sep 17 00:00:00 2001 From: Home Assistant Bot Date: Thu, 16 May 2019 23:36:57 -0700 Subject: [PATCH] New Crowdin translations (#258) * New translations frontend_external_auth.md (Norwegian) * New translations frontend_development.md (Norwegian) * New translations frontend_data.md (Norwegian) * New translations frontend_creating_custom_ui.md (Norwegian) * New translations frontend_creating_custom_panels.md (Norwegian) * New translations hassio_addon_tutorial.md (Norwegian) * New translations hassio_hass.md (Norwegian) * New translations frontend_add_websocket_api.md (Norwegian) * New translations internationalization_translation.md (Norwegian) * New translations en.json (Norwegian) * New translations releasing.md (Norwegian) * New translations misc.md (Norwegian) * New translations maintenance.md (Norwegian) * New translations lovelace_index.md (Norwegian) * New translations documentation_index.md (Korean) * New translations hassio_hass.md (Korean) * New translations lovelace_custom_card.md (Norwegian) * New translations internationalization_index.md (Norwegian) * New translations integration_quality_scale_index.md (Norwegian) * New translations internationalization_custom_component_localization.md (Norwegian) * New translations internationalization_backend_localization.md (Norwegian) * New translations intent_index.md (Norwegian) * New translations intent_handling.md (Norwegian) * New translations intent_firing.md (Norwegian) * New translations intent_conversation.md (Norwegian) * New translations intent_builtin.md (Norwegian) * New translations frontend_architecture.md (Norwegian) * New translations frontend_add_more_info.md (Norwegian) * New translations app_integration_notifications.md (Polish) * New translations development_validation.md (Norwegian) * New translations entity_alarm_control_panel.md (Norwegian) * New translations entity_air_quality.md (Norwegian) * New translations documentation_standards.md (Norwegian) * New translations documentation_index.md (Norwegian) * New translations documentation_create_page.md (Norwegian) * New translations device_registry_index.md (Norwegian) * New translations development_typing.md (Norwegian) * New translations entity_climate.md (Norwegian) * New translations development_testing.md (Norwegian) * New translations development_submitting.md (Norwegian) * New translations development_index.md (Norwegian) * New translations development_guidelines.md (Norwegian) * New translations development_environment.md (Norwegian) * New translations development_checklist.md (Norwegian) * New translations development_catching_up.md (Norwegian) * New translations entity_binary_sensor.md (Norwegian) * New translations entity_cover.md (Norwegian) * New translations frontend_add_card.md (Norwegian) * New translations entity_vacuum.md (Norwegian) * New translations external_api_websocket.md (Norwegian) * New translations external_api_server_sent_events.md (Norwegian) * New translations external_api_rest_python.md (Norwegian) * New translations external_api_rest.md (Norwegian) * New translations entity_weather.md (Norwegian) * New translations entity_water_heater.md (Norwegian) * New translations entity_switch.md (Norwegian) * New translations entity_fan.md (Norwegian) * New translations entity_sensor.md (Norwegian) * New translations entity_remote.md (Norwegian) * New translations entity_registry_index.md (Norwegian) * New translations entity_media_player.md (Norwegian) * New translations entity_lock.md (Norwegian) * New translations entity_light.md (Norwegian) * New translations entity_index.md (Norwegian) * New translations app_integration_index.md (Polish) * New translations app_integration_sending_data.md (Polish) * New translations dev_101_services.md (Norwegian) * New translations documentation_create_page.md (Polish) * New translations entity_climate.md (Polish) * New translations entity_binary_sensor.md (Polish) * New translations entity_alarm_control_panel.md (Polish) * New translations entity_air_quality.md (Polish) * New translations documentation_standards.md (Polish) * New translations documentation_index.md (Polish) * New translations device_registry_index.md (Polish) * New translations entity_fan.md (Polish) * New translations development_validation.md (Polish) * New translations development_typing.md (Polish) * New translations development_testing.md (Polish) * New translations development_submitting.md (Polish) * New translations development_index.md (Polish) * New translations development_guidelines.md (Polish) * New translations development_checklist.md (Polish) * New translations entity_cover.md (Polish) * New translations entity_index.md (Polish) * New translations dev_101_states.md (Polish) * New translations entity_weather.md (Polish) * New translations app_integration_index.md (Dutch) * New translations frontend_add_card.md (Polish) * New translations external_api_websocket.md (Polish) * New translations external_api_server_sent_events.md (Polish) * New translations external_api_rest_python.md (Polish) * New translations external_api_rest.md (Polish) * New translations entity_water_heater.md (Polish) * New translations entity_light.md (Polish) * New translations entity_vacuum.md (Polish) * New translations entity_switch.md (Polish) * New translations entity_sensor.md (Polish) * New translations entity_remote.md (Polish) * New translations entity_registry_index.md (Polish) * New translations entity_media_player.md (Polish) * New translations entity_lock.md (Polish) * New translations development_catching_up.md (Polish) * New translations dev_101_services.md (Polish) * New translations app_integration_sensors.md (Polish) * New translations asyncio_categorizing_functions.md (Polish) * New translations auth_index.md (Polish) * New translations auth_auth_provider.md (Polish) * New translations auth_auth_module.md (Polish) * New translations auth_api.md (Polish) * New translations asyncio_working_with_async.md (Polish) * New translations asyncio_index.md (Polish) * New translations asyncio_101.md (Polish) * New translations config_entries_config_flow_handler.md (Polish) * New translations area_registry_index.md (Polish) * New translations architecture_index.md (Polish) * New translations architecture_hassio.md (Polish) * New translations architecture_entities.md (Polish) * New translations architecture_components.md (Polish) * New translations app_integration_webview.md (Polish) * New translations app_integration_setup.md (Polish) * New translations auth_permissions.md (Polish) * New translations config_entries_index.md (Polish) * New translations dev_101_index.md (Polish) * New translations creating_platform_example_light.md (Polish) * New translations dev_101_hass.md (Polish) * New translations dev_101_events.md (Polish) * New translations dev_101_config.md (Polish) * New translations data_entry_flow_index.md (Polish) * New translations creating_platform_index.md (Polish) * New translations creating_platform_example_sensor.md (Polish) * New translations creating_platform_code_review.md (Polish) * New translations config_entries_options_flow_handler.md (Polish) * New translations creating_integration_manifest.md (Polish) * New translations creating_integration_file_structure.md (Polish) * New translations creating_component_index.md (Polish) * New translations creating_component_generic_discovery.md (Polish) * New translations creating_component_deps_and_reqs.md (Polish) * New translations creating_component_code_review.md (Polish) * New translations configuration_yaml_index.md (Polish) * New translations dev_101_states.md (Norwegian) * New translations development_environment.md (Polish) * New translations dev_101_index.md (Norwegian) * New translations development_testing.md (Dutch) * New translations documentation_standards.md (Dutch) * New translations documentation_index.md (Dutch) * New translations documentation_create_page.md (Dutch) * New translations device_registry_index.md (Dutch) * New translations development_validation.md (Dutch) * New translations development_typing.md (Dutch) * New translations development_submitting.md (Dutch) * New translations entity_alarm_control_panel.md (Dutch) * New translations development_index.md (Dutch) * New translations development_guidelines.md (Dutch) * New translations development_environment.md (Dutch) * New translations development_checklist.md (Dutch) * New translations development_catching_up.md (Dutch) * New translations dev_101_states.md (Dutch) * New translations dev_101_services.md (Dutch) * New translations entity_air_quality.md (Dutch) * New translations entity_binary_sensor.md (Dutch) * New translations dev_101_hass.md (Dutch) * New translations entity_sensor.md (Dutch) * New translations external_api_rest_python.md (Dutch) * New translations external_api_rest.md (Dutch) * New translations entity_weather.md (Dutch) * New translations entity_water_heater.md (Dutch) * New translations entity_vacuum.md (Dutch) * New translations entity_switch.md (Dutch) * New translations entity_remote.md (Dutch) * New translations entity_climate.md (Dutch) * New translations entity_registry_index.md (Dutch) * New translations entity_media_player.md (Dutch) * New translations entity_lock.md (Dutch) * New translations entity_light.md (Dutch) * New translations entity_index.md (Dutch) * New translations entity_fan.md (Dutch) * New translations entity_cover.md (Dutch) * New translations dev_101_index.md (Dutch) * New translations dev_101_events.md (Dutch) * New translations external_api_websocket.md (Dutch) * New translations architecture_hassio.md (Dutch) * New translations asyncio_working_with_async.md (Dutch) * New translations asyncio_index.md (Dutch) * New translations asyncio_categorizing_functions.md (Dutch) * New translations asyncio_101.md (Dutch) * New translations area_registry_index.md (Dutch) * New translations architecture_index.md (Dutch) * New translations architecture_entities.md (Dutch) * New translations auth_auth_module.md (Dutch) * New translations architecture_components.md (Dutch) * New translations app_integration_webview.md (Dutch) * New translations app_integration_setup.md (Dutch) * New translations app_integration_sensors.md (Dutch) * New translations app_integration_sending_data.md (Dutch) * New translations app_integration_notifications.md (Dutch) * New translations dev_101_hass.md (Norwegian) * New translations auth_api.md (Dutch) * New translations auth_auth_provider.md (Dutch) * New translations dev_101_config.md (Dutch) * New translations creating_integration_file_structure.md (Dutch) * New translations data_entry_flow_index.md (Dutch) * New translations creating_platform_index.md (Dutch) * New translations creating_platform_example_sensor.md (Dutch) * New translations creating_platform_example_light.md (Dutch) * New translations creating_platform_code_review.md (Dutch) * New translations creating_integration_manifest.md (Dutch) * New translations creating_component_index.md (Dutch) * New translations auth_permissions.md (Dutch) * New translations creating_component_generic_discovery.md (Dutch) * New translations creating_component_deps_and_reqs.md (Dutch) * New translations creating_component_code_review.md (Dutch) * New translations configuration_yaml_index.md (Dutch) * New translations config_entries_options_flow_handler.md (Dutch) * New translations config_entries_index.md (Dutch) * New translations config_entries_config_flow_handler.md (Dutch) * New translations external_api_server_sent_events.md (Dutch) * New translations auth_index.md (Dutch) * New translations frontend_add_card.md (Dutch) * New translations asyncio_101.md (Norwegian) * New translations auth_auth_provider.md (Norwegian) * New translations auth_auth_module.md (Norwegian) * New translations auth_api.md (Norwegian) * New translations asyncio_working_with_async.md (Norwegian) * New translations asyncio_index.md (Norwegian) * New translations asyncio_categorizing_functions.md (Norwegian) * New translations area_registry_index.md (Norwegian) * New translations auth_permissions.md (Norwegian) * New translations architecture_index.md (Norwegian) * New translations architecture_hassio.md (Norwegian) * New translations architecture_entities.md (Norwegian) * New translations architecture_components.md (Norwegian) * New translations app_integration_webview.md (Norwegian) * New translations app_integration_setup.md (Norwegian) * New translations app_integration_sensors.md (Norwegian) * New translations auth_index.md (Norwegian) * New translations config_entries_config_flow_handler.md (Norwegian) * New translations app_integration_notifications.md (Norwegian) * New translations creating_platform_example_light.md (Norwegian) * New translations dev_101_events.md (Norwegian) * New translations dev_101_config.md (Norwegian) * New translations frontend_add_more_info.md (Dutch) * New translations data_entry_flow_index.md (Norwegian) * New translations creating_platform_index.md (Norwegian) * New translations creating_platform_example_sensor.md (Norwegian) * New translations creating_platform_code_review.md (Norwegian) * New translations config_entries_index.md (Norwegian) * New translations creating_integration_manifest.md (Norwegian) * New translations creating_integration_file_structure.md (Norwegian) * New translations creating_component_index.md (Norwegian) --- website/i18n/no-NO.json | 1529 +++++++++++++++++ .../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 + 301 files changed, 24952 insertions(+) create mode 100644 website/i18n/no-NO.json create mode 100644 website/translated_docs/ko-KR/version-0.74.0/lovelace_custom_card.md create mode 100644 website/translated_docs/ko-KR/version-0.78.0/frontend_add_more_info.md create mode 100644 website/translated_docs/ko-KR/version-0.78.0/frontend_external_auth.md create mode 100644 website/translated_docs/ko-KR/version-0.78.0/hassio_addon_communication.md create mode 100644 website/translated_docs/ko-KR/version-0.78.0/hassio_addon_config.md create mode 100644 website/translated_docs/ko-KR/version-0.78.0/hassio_addon_security.md create mode 100644 website/translated_docs/ko-KR/version-0.79.0/creating_component_code_review.md create mode 100644 website/translated_docs/ko-KR/version-0.79.0/creating_platform_code_review.md create mode 100644 website/translated_docs/ko-KR/version-0.79.0/development_environment.md create mode 100644 website/translated_docs/ko-KR/version-0.79.0/documentation_create_page.md create mode 100644 website/translated_docs/ko-KR/version-0.79.0/documentation_index.md create mode 100644 website/translated_docs/ko-KR/version-0.79.0/hassio_addon_communication.md create mode 100644 website/translated_docs/ko-KR/version-0.79.0/hassio_hass.md create mode 100644 website/translated_docs/ko-KR/version-0.86.0/hassio_addon_config.md create mode 100644 website/translated_docs/ko-KR/version-0.87.0/area_registry_index.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_component_code_review.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_component_deps_and_reqs.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_component_generic_discovery.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_component_index.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_integration_file_structure.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_integration_manifest.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_platform_code_review.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_platform_example_light.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_platform_example_sensor.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/creating_platform_index.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/dev_101_services.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/dev_101_states.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/development_checklist.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/development_guidelines.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/development_index.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/development_validation.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/entity_sensor.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/internationalization_translation.md create mode 100644 website/translated_docs/ko-KR/version-0.91.2/maintenance.md create mode 100644 website/translated_docs/ko-KR/version-0.92.0/app_integration_setup.md create mode 100644 website/translated_docs/ko-KR/version-0.92.0/auth_auth_module.md create mode 100644 website/translated_docs/ko-KR/version-0.92.0/creating_integration_manifest.md create mode 100644 website/translated_docs/ko-KR/version-0.92.0/creating_platform_index.md create mode 100644 website/translated_docs/ko-KR/version-0.92.0/development_submitting.md create mode 100644 website/translated_docs/ko-KR/version-0.92.0/entity_climate.md create mode 100644 website/translated_docs/ko-KR/version-0.92.0/entity_fan.md create mode 100644 website/translated_docs/ko-KR/version-0.92.0/entity_registry_index.md create mode 100644 website/translated_docs/ko/app_integration_notifications.md create mode 100644 website/translated_docs/nl/app_integration_index.md create mode 100644 website/translated_docs/nl/app_integration_notifications.md create mode 100644 website/translated_docs/nl/app_integration_sending_data.md create mode 100644 website/translated_docs/nl/app_integration_sensors.md create mode 100644 website/translated_docs/nl/app_integration_setup.md create mode 100644 website/translated_docs/nl/app_integration_webview.md create mode 100644 website/translated_docs/nl/architecture_components.md create mode 100644 website/translated_docs/nl/architecture_entities.md create mode 100644 website/translated_docs/nl/architecture_hassio.md create mode 100644 website/translated_docs/nl/architecture_index.md create mode 100644 website/translated_docs/nl/area_registry_index.md create mode 100644 website/translated_docs/nl/asyncio_101.md create mode 100644 website/translated_docs/nl/asyncio_categorizing_functions.md create mode 100644 website/translated_docs/nl/asyncio_index.md create mode 100644 website/translated_docs/nl/asyncio_working_with_async.md create mode 100644 website/translated_docs/nl/auth_api.md create mode 100644 website/translated_docs/nl/auth_auth_module.md create mode 100644 website/translated_docs/nl/auth_auth_provider.md create mode 100644 website/translated_docs/nl/auth_index.md create mode 100644 website/translated_docs/nl/auth_permissions.md create mode 100644 website/translated_docs/nl/config_entries_config_flow_handler.md create mode 100644 website/translated_docs/nl/config_entries_index.md create mode 100644 website/translated_docs/nl/config_entries_options_flow_handler.md create mode 100644 website/translated_docs/nl/configuration_yaml_index.md create mode 100644 website/translated_docs/nl/creating_component_code_review.md create mode 100644 website/translated_docs/nl/creating_component_deps_and_reqs.md create mode 100644 website/translated_docs/nl/creating_component_generic_discovery.md create mode 100644 website/translated_docs/nl/creating_component_index.md create mode 100644 website/translated_docs/nl/creating_integration_file_structure.md create mode 100644 website/translated_docs/nl/creating_integration_manifest.md create mode 100644 website/translated_docs/nl/creating_platform_code_review.md create mode 100644 website/translated_docs/nl/creating_platform_example_light.md create mode 100644 website/translated_docs/nl/creating_platform_example_sensor.md create mode 100644 website/translated_docs/nl/creating_platform_index.md create mode 100644 website/translated_docs/nl/data_entry_flow_index.md create mode 100644 website/translated_docs/nl/dev_101_config.md create mode 100644 website/translated_docs/nl/dev_101_events.md create mode 100644 website/translated_docs/nl/dev_101_hass.md create mode 100644 website/translated_docs/nl/dev_101_index.md create mode 100644 website/translated_docs/nl/dev_101_services.md create mode 100644 website/translated_docs/nl/dev_101_states.md create mode 100644 website/translated_docs/nl/development_catching_up.md create mode 100644 website/translated_docs/nl/development_checklist.md create mode 100644 website/translated_docs/nl/development_environment.md create mode 100644 website/translated_docs/nl/development_guidelines.md create mode 100644 website/translated_docs/nl/development_index.md create mode 100644 website/translated_docs/nl/development_submitting.md create mode 100644 website/translated_docs/nl/development_testing.md create mode 100644 website/translated_docs/nl/development_typing.md create mode 100644 website/translated_docs/nl/development_validation.md create mode 100644 website/translated_docs/nl/device_registry_index.md create mode 100644 website/translated_docs/nl/documentation_create_page.md create mode 100644 website/translated_docs/nl/documentation_index.md create mode 100644 website/translated_docs/nl/documentation_standards.md create mode 100644 website/translated_docs/nl/entity_air_quality.md create mode 100644 website/translated_docs/nl/entity_alarm_control_panel.md create mode 100644 website/translated_docs/nl/entity_binary_sensor.md create mode 100644 website/translated_docs/nl/entity_climate.md create mode 100644 website/translated_docs/nl/entity_cover.md create mode 100644 website/translated_docs/nl/entity_fan.md create mode 100644 website/translated_docs/nl/entity_index.md create mode 100644 website/translated_docs/nl/entity_light.md create mode 100644 website/translated_docs/nl/entity_lock.md create mode 100644 website/translated_docs/nl/entity_media_player.md create mode 100644 website/translated_docs/nl/entity_registry_index.md create mode 100644 website/translated_docs/nl/entity_remote.md create mode 100644 website/translated_docs/nl/entity_sensor.md create mode 100644 website/translated_docs/nl/entity_switch.md create mode 100644 website/translated_docs/nl/entity_vacuum.md create mode 100644 website/translated_docs/nl/entity_water_heater.md create mode 100644 website/translated_docs/nl/entity_weather.md create mode 100644 website/translated_docs/nl/external_api_rest.md create mode 100644 website/translated_docs/nl/external_api_rest_python.md create mode 100644 website/translated_docs/nl/external_api_server_sent_events.md create mode 100644 website/translated_docs/nl/external_api_websocket.md create mode 100644 website/translated_docs/nl/frontend_add_card.md create mode 100644 website/translated_docs/nl/frontend_add_more_info.md create mode 100644 website/translated_docs/no-NO/app_integration_notifications.md create mode 100644 website/translated_docs/no-NO/app_integration_sensors.md create mode 100644 website/translated_docs/no-NO/app_integration_setup.md create mode 100644 website/translated_docs/no-NO/app_integration_webview.md create mode 100644 website/translated_docs/no-NO/architecture_components.md create mode 100644 website/translated_docs/no-NO/architecture_entities.md create mode 100644 website/translated_docs/no-NO/architecture_hassio.md create mode 100644 website/translated_docs/no-NO/architecture_index.md create mode 100644 website/translated_docs/no-NO/area_registry_index.md create mode 100644 website/translated_docs/no-NO/asyncio_101.md create mode 100644 website/translated_docs/no-NO/asyncio_categorizing_functions.md create mode 100644 website/translated_docs/no-NO/asyncio_index.md create mode 100644 website/translated_docs/no-NO/asyncio_working_with_async.md create mode 100644 website/translated_docs/no-NO/auth_api.md create mode 100644 website/translated_docs/no-NO/auth_auth_module.md create mode 100644 website/translated_docs/no-NO/auth_auth_provider.md create mode 100644 website/translated_docs/no-NO/auth_index.md create mode 100644 website/translated_docs/no-NO/auth_permissions.md create mode 100644 website/translated_docs/no-NO/config_entries_config_flow_handler.md create mode 100644 website/translated_docs/no-NO/config_entries_index.md create mode 100644 website/translated_docs/no-NO/creating_component_index.md create mode 100644 website/translated_docs/no-NO/creating_integration_file_structure.md create mode 100644 website/translated_docs/no-NO/creating_integration_manifest.md create mode 100644 website/translated_docs/no-NO/creating_platform_code_review.md create mode 100644 website/translated_docs/no-NO/creating_platform_example_light.md create mode 100644 website/translated_docs/no-NO/creating_platform_example_sensor.md create mode 100644 website/translated_docs/no-NO/creating_platform_index.md create mode 100644 website/translated_docs/no-NO/data_entry_flow_index.md create mode 100644 website/translated_docs/no-NO/dev_101_config.md create mode 100644 website/translated_docs/no-NO/dev_101_events.md create mode 100644 website/translated_docs/no-NO/dev_101_hass.md create mode 100644 website/translated_docs/no-NO/dev_101_index.md create mode 100644 website/translated_docs/no-NO/dev_101_services.md create mode 100644 website/translated_docs/no-NO/dev_101_states.md create mode 100644 website/translated_docs/no-NO/development_catching_up.md create mode 100644 website/translated_docs/no-NO/development_checklist.md create mode 100644 website/translated_docs/no-NO/development_environment.md create mode 100644 website/translated_docs/no-NO/development_guidelines.md create mode 100644 website/translated_docs/no-NO/development_index.md create mode 100644 website/translated_docs/no-NO/development_submitting.md create mode 100644 website/translated_docs/no-NO/development_testing.md create mode 100644 website/translated_docs/no-NO/development_typing.md create mode 100644 website/translated_docs/no-NO/development_validation.md create mode 100644 website/translated_docs/no-NO/device_registry_index.md create mode 100644 website/translated_docs/no-NO/documentation_create_page.md create mode 100644 website/translated_docs/no-NO/documentation_index.md create mode 100644 website/translated_docs/no-NO/documentation_standards.md create mode 100644 website/translated_docs/no-NO/entity_air_quality.md create mode 100644 website/translated_docs/no-NO/entity_alarm_control_panel.md create mode 100644 website/translated_docs/no-NO/entity_binary_sensor.md create mode 100644 website/translated_docs/no-NO/entity_climate.md create mode 100644 website/translated_docs/no-NO/entity_cover.md create mode 100644 website/translated_docs/no-NO/entity_fan.md create mode 100644 website/translated_docs/no-NO/entity_index.md create mode 100644 website/translated_docs/no-NO/entity_light.md create mode 100644 website/translated_docs/no-NO/entity_lock.md create mode 100644 website/translated_docs/no-NO/entity_media_player.md create mode 100644 website/translated_docs/no-NO/entity_registry_index.md create mode 100644 website/translated_docs/no-NO/entity_remote.md create mode 100644 website/translated_docs/no-NO/entity_sensor.md create mode 100644 website/translated_docs/no-NO/entity_switch.md create mode 100644 website/translated_docs/no-NO/entity_vacuum.md create mode 100644 website/translated_docs/no-NO/entity_water_heater.md create mode 100644 website/translated_docs/no-NO/entity_weather.md create mode 100644 website/translated_docs/no-NO/external_api_rest.md create mode 100644 website/translated_docs/no-NO/external_api_rest_python.md create mode 100644 website/translated_docs/no-NO/external_api_server_sent_events.md create mode 100644 website/translated_docs/no-NO/external_api_websocket.md create mode 100644 website/translated_docs/no-NO/frontend_add_card.md create mode 100644 website/translated_docs/no-NO/frontend_add_more_info.md create mode 100644 website/translated_docs/no-NO/frontend_add_websocket_api.md create mode 100644 website/translated_docs/no-NO/frontend_architecture.md create mode 100644 website/translated_docs/no-NO/frontend_creating_custom_panels.md create mode 100644 website/translated_docs/no-NO/frontend_creating_custom_ui.md create mode 100644 website/translated_docs/no-NO/frontend_data.md create mode 100644 website/translated_docs/no-NO/frontend_development.md create mode 100644 website/translated_docs/no-NO/frontend_external_auth.md create mode 100644 website/translated_docs/no-NO/frontend_index.md create mode 100644 website/translated_docs/no-NO/hassio_addon_communication.md create mode 100644 website/translated_docs/no-NO/hassio_addon_config.md create mode 100644 website/translated_docs/no-NO/hassio_addon_index.md create mode 100644 website/translated_docs/no-NO/hassio_addon_presentation.md create mode 100644 website/translated_docs/no-NO/hassio_addon_publishing.md create mode 100644 website/translated_docs/no-NO/hassio_addon_repository.md create mode 100644 website/translated_docs/no-NO/hassio_addon_security.md create mode 100644 website/translated_docs/no-NO/hassio_addon_testing.md create mode 100644 website/translated_docs/no-NO/hassio_addon_tutorial.md create mode 100644 website/translated_docs/no-NO/hassio_debugging.md create mode 100644 website/translated_docs/no-NO/hassio_hass.md create mode 100644 website/translated_docs/no-NO/integration_quality_scale_index.md create mode 100644 website/translated_docs/no-NO/intent_builtin.md create mode 100644 website/translated_docs/no-NO/intent_conversation.md create mode 100644 website/translated_docs/no-NO/intent_firing.md create mode 100644 website/translated_docs/no-NO/intent_handling.md create mode 100644 website/translated_docs/no-NO/intent_index.md create mode 100644 website/translated_docs/no-NO/internationalization_backend_localization.md create mode 100644 website/translated_docs/no-NO/internationalization_custom_component_localization.md create mode 100644 website/translated_docs/no-NO/internationalization_index.md create mode 100644 website/translated_docs/no-NO/internationalization_translation.md create mode 100644 website/translated_docs/no-NO/lovelace_custom_card.md create mode 100644 website/translated_docs/no-NO/lovelace_index.md create mode 100644 website/translated_docs/no-NO/maintenance.md create mode 100644 website/translated_docs/no-NO/misc.md create mode 100644 website/translated_docs/no-NO/releasing.md create mode 100644 website/translated_docs/pl/app_integration_index.md create mode 100644 website/translated_docs/pl/app_integration_notifications.md create mode 100644 website/translated_docs/pl/app_integration_sending_data.md create mode 100644 website/translated_docs/pl/app_integration_sensors.md create mode 100644 website/translated_docs/pl/app_integration_setup.md create mode 100644 website/translated_docs/pl/app_integration_webview.md create mode 100644 website/translated_docs/pl/architecture_components.md create mode 100644 website/translated_docs/pl/architecture_entities.md create mode 100644 website/translated_docs/pl/architecture_hassio.md create mode 100644 website/translated_docs/pl/architecture_index.md create mode 100644 website/translated_docs/pl/area_registry_index.md create mode 100644 website/translated_docs/pl/asyncio_101.md create mode 100644 website/translated_docs/pl/asyncio_categorizing_functions.md create mode 100644 website/translated_docs/pl/asyncio_index.md create mode 100644 website/translated_docs/pl/asyncio_working_with_async.md create mode 100644 website/translated_docs/pl/auth_api.md create mode 100644 website/translated_docs/pl/auth_auth_module.md create mode 100644 website/translated_docs/pl/auth_auth_provider.md create mode 100644 website/translated_docs/pl/auth_index.md create mode 100644 website/translated_docs/pl/auth_permissions.md create mode 100644 website/translated_docs/pl/config_entries_config_flow_handler.md create mode 100644 website/translated_docs/pl/config_entries_index.md create mode 100644 website/translated_docs/pl/config_entries_options_flow_handler.md create mode 100644 website/translated_docs/pl/configuration_yaml_index.md create mode 100644 website/translated_docs/pl/creating_component_code_review.md create mode 100644 website/translated_docs/pl/creating_component_deps_and_reqs.md create mode 100644 website/translated_docs/pl/creating_component_generic_discovery.md create mode 100644 website/translated_docs/pl/creating_component_index.md create mode 100644 website/translated_docs/pl/creating_integration_file_structure.md create mode 100644 website/translated_docs/pl/creating_integration_manifest.md create mode 100644 website/translated_docs/pl/creating_platform_code_review.md create mode 100644 website/translated_docs/pl/creating_platform_example_light.md create mode 100644 website/translated_docs/pl/creating_platform_example_sensor.md create mode 100644 website/translated_docs/pl/creating_platform_index.md create mode 100644 website/translated_docs/pl/data_entry_flow_index.md create mode 100644 website/translated_docs/pl/dev_101_config.md create mode 100644 website/translated_docs/pl/dev_101_events.md create mode 100644 website/translated_docs/pl/dev_101_hass.md create mode 100644 website/translated_docs/pl/dev_101_index.md create mode 100644 website/translated_docs/pl/dev_101_services.md create mode 100644 website/translated_docs/pl/dev_101_states.md create mode 100644 website/translated_docs/pl/development_catching_up.md create mode 100644 website/translated_docs/pl/development_checklist.md create mode 100644 website/translated_docs/pl/development_environment.md create mode 100644 website/translated_docs/pl/development_guidelines.md create mode 100644 website/translated_docs/pl/development_index.md create mode 100644 website/translated_docs/pl/development_submitting.md create mode 100644 website/translated_docs/pl/development_testing.md create mode 100644 website/translated_docs/pl/development_typing.md create mode 100644 website/translated_docs/pl/development_validation.md create mode 100644 website/translated_docs/pl/device_registry_index.md create mode 100644 website/translated_docs/pl/documentation_create_page.md create mode 100644 website/translated_docs/pl/documentation_index.md create mode 100644 website/translated_docs/pl/documentation_standards.md create mode 100644 website/translated_docs/pl/entity_air_quality.md create mode 100644 website/translated_docs/pl/entity_alarm_control_panel.md create mode 100644 website/translated_docs/pl/entity_binary_sensor.md create mode 100644 website/translated_docs/pl/entity_climate.md create mode 100644 website/translated_docs/pl/entity_cover.md create mode 100644 website/translated_docs/pl/entity_fan.md create mode 100644 website/translated_docs/pl/entity_index.md create mode 100644 website/translated_docs/pl/entity_light.md create mode 100644 website/translated_docs/pl/entity_lock.md create mode 100644 website/translated_docs/pl/entity_media_player.md create mode 100644 website/translated_docs/pl/entity_registry_index.md create mode 100644 website/translated_docs/pl/entity_remote.md create mode 100644 website/translated_docs/pl/entity_sensor.md create mode 100644 website/translated_docs/pl/entity_switch.md create mode 100644 website/translated_docs/pl/entity_vacuum.md create mode 100644 website/translated_docs/pl/entity_water_heater.md create mode 100644 website/translated_docs/pl/entity_weather.md create mode 100644 website/translated_docs/pl/external_api_rest.md create mode 100644 website/translated_docs/pl/external_api_rest_python.md create mode 100644 website/translated_docs/pl/external_api_server_sent_events.md create mode 100644 website/translated_docs/pl/external_api_websocket.md create mode 100644 website/translated_docs/pl/frontend_add_card.md diff --git a/website/i18n/no-NO.json b/website/i18n/no-NO.json new file mode 100644 index 00000000..24b3654b --- /dev/null +++ b/website/i18n/no-NO.json @@ -0,0 +1,1529 @@ +{ + "_comment": "This file is auto-generated by write-translations.js", + "localized-strings": { + "next": "Next", + "previous": "Previous", + "tagline": "All you need to start developing for Home Assistant", + "docs": { + "app_integration_index": { + "title": "Native App Integration", + "sidebar_label": "Introduction" + }, + "app_integration_notifications": { + "title": "Push Notifications" + }, + "app_integration_sending_data": { + "title": "Sending data home" + }, + "app_integration_sensors": { + "title": "Sensors" + }, + "app_integration_setup": { + "title": "Connecting to an instance" + }, + "app_integration_webview": { + "title": "Authenticated Webview" + }, + "architecture_components": { + "title": "Components Architecture", + "sidebar_label": "Components" + }, + "architecture_entities": { + "title": "Entity Architecture", + "sidebar_label": "Entity" + }, + "architecture_hassio": { + "title": "Hass.io Architecture", + "sidebar_label": "Hass.io" + }, + "architecture_index": { + "title": "Architecture", + "sidebar_label": "Introduction" + }, + "area_registry_index": { + "title": "Area Registry", + "sidebar_label": "Introduction" + }, + "asyncio_101": { + "title": "Asyncio 101" + }, + "asyncio_categorizing_functions": { + "title": "Categorizing Functions" + }, + "asyncio_index": { + "title": "Asynchronous Programming", + "sidebar_label": "Introduction" + }, + "asyncio_working_with_async": { + "title": "Working with Async" + }, + "auth_api": { + "title": "Authentication API", + "sidebar_label": "API" + }, + "auth_auth_module": { + "title": "Multi-factor Authentication Modules" + }, + "auth_auth_provider": { + "title": "Authentication Providers" + }, + "auth_index": { + "title": "Authentication", + "sidebar_label": "Introduction" + }, + "auth_permissions": { + "title": "Permissions" + }, + "config_entries_config_flow_handler": { + "title": "Integration Configuration", + "sidebar_label": "Configuration" + }, + "config_entries_index": { + "title": "Config Entries", + "sidebar_label": "Introduction" + }, + "config_entries_options_flow_handler": { + "title": "Integration Configuration Options", + "sidebar_label": "Configuration Options" + }, + "configuration_yaml_index": { + "title": "Integration Configuration via YAML", + "sidebar_label": "Configuration via YAML" + }, + "creating_component_code_review": { + "title": "Checklist for creating a component", + "sidebar_label": "Component Checklist" + }, + "creating_component_deps_and_reqs": { + "title": "creating_component_deps_and_reqs" + }, + "creating_component_generic_discovery": { + "title": "Integration with Multiple Platforms", + "sidebar_label": "Multiple platforms" + }, + "creating_component_index": { + "title": "Creating a Minimal Component", + "sidebar_label": "Minimal Component" + }, + "creating_integration_file_structure": { + "title": "Integration File Structure", + "sidebar_label": "File Structure" + }, + "creating_integration_manifest": { + "title": "Integration Manifest", + "sidebar_label": "Manifest" + }, + "creating_platform_code_review": { + "title": "Checklist for creating a platform", + "sidebar_label": "Platform Checklist" + }, + "creating_platform_example_light": { + "title": "creating_platform_example_light" + }, + "creating_platform_example_sensor": { + "title": "creating_platform_example_sensor" + }, + "creating_platform_index": { + "title": "Integration Platforms", + "sidebar_label": "Platforms" + }, + "data_entry_flow_index": { + "title": "Data Entry Flow", + "sidebar_label": "Introduction" + }, + "dev_101_config": { + "title": "Using Config" + }, + "dev_101_events": { + "title": "Using Events" + }, + "dev_101_hass": { + "title": "Hass object" + }, + "dev_101_index": { + "title": "Development 101", + "sidebar_label": "Introduction" + }, + "dev_101_services": { + "title": "Integration Services", + "sidebar_label": "Custom Services" + }, + "dev_101_states": { + "title": "Using States" + }, + "development_catching_up": { + "title": "Catching up with Reality" + }, + "development_checklist": { + "title": "Development Checklist", + "sidebar_label": "Introduction" + }, + "development_environment": { + "title": "Set up Development Environment" + }, + "development_guidelines": { + "title": "Style guidelines" + }, + "development_index": { + "title": "Starting with Development", + "sidebar_label": "Introduction" + }, + "development_submitting": { + "title": "Submit your work" + }, + "development_testing": { + "title": "Testing your code" + }, + "development_typing": { + "title": "Adding type hints to your code" + }, + "development_validation": { + "title": "Validate the input" + }, + "device_registry_index": { + "title": "Device Registry", + "sidebar_label": "Introduction" + }, + "documentation_create_page": { + "title": "Create a new page" + }, + "documentation_index": { + "title": "Documentation" + }, + "documentation_standards": { + "title": "Standards" + }, + "entity_air_quality": { + "title": "Air Quality Entity", + "sidebar_label": "Air Quality" + }, + "entity_alarm_control_panel": { + "title": "Alarm Control Panel Entity", + "sidebar_label": "Alarm Control Panel" + }, + "entity_binary_sensor": { + "title": "Binary Sensor Entity", + "sidebar_label": "Binary Sensor" + }, + "entity_climate": { + "title": "Climate Entity", + "sidebar_label": "Climate" + }, + "entity_cover": { + "title": "Cover Entity", + "sidebar_label": "Cover" + }, + "entity_fan": { + "title": "Fan Entity", + "sidebar_label": "Fan" + }, + "entity_index": { + "title": "Entity", + "sidebar_label": "Introduction" + }, + "entity_light": { + "title": "Light Entity", + "sidebar_label": "Light" + }, + "entity_lock": { + "title": "Lock Entity", + "sidebar_label": "Lock" + }, + "entity_media_player": { + "title": "Media Player Entity", + "sidebar_label": "Media Player" + }, + "entity_registry_index": { + "title": "Entity Registry", + "sidebar_label": "Introduction" + }, + "entity_remote": { + "title": "Remote Entity", + "sidebar_label": "Remote" + }, + "entity_sensor": { + "title": "Sensor Entity", + "sidebar_label": "Sensor" + }, + "entity_switch": { + "title": "Switch Entity", + "sidebar_label": "Switch" + }, + "entity_vacuum": { + "title": "Vacuum Entity", + "sidebar_label": "Vacuum" + }, + "entity_water_heater": { + "title": "Water Heater Entity", + "sidebar_label": "Water Heater" + }, + "entity_weather": { + "title": "Weather Entity", + "sidebar_label": "Weather" + }, + "external_api_rest_python": { + "title": "REST API - Python bindings" + }, + "external_api_rest": { + "title": "REST API" + }, + "external_api_server_sent_events": { + "title": "Server-sent events" + }, + "external_api_websocket": { + "title": "WebSocket API" + }, + "frontend_add_card": { + "title": "Adding state card" + }, + "frontend_add_more_info": { + "title": "Adding more info dialogs" + }, + "frontend_add_websocket_api": { + "title": "Extending the WebSocket API" + }, + "frontend_architecture": { + "title": "Home Assistant Frontend Architecture", + "sidebar_label": "Architecture" + }, + "frontend_creating_custom_panels": { + "title": "Creating custom panels" + }, + "frontend_creating_custom_ui": { + "title": "Creating custom UI" + }, + "frontend_data": { + "title": "Frontend data", + "sidebar_label": "Data" + }, + "frontend_development": { + "title": "Frontend development", + "sidebar_label": "Development" + }, + "frontend_external_auth": { + "title": "External Authentication" + }, + "frontend_index": { + "title": "Home Assistant Frontend", + "sidebar_label": "Introduction" + }, + "hassio_addon_communication": { + "title": "Add-On Communication" + }, + "hassio_addon_config": { + "title": "Add-On Configuration" + }, + "hassio_addon_index": { + "title": "Developing an add-on", + "sidebar_label": "Introduction" + }, + "hassio_addon_presentation": { + "title": "Presenting your add-on" + }, + "hassio_addon_publishing": { + "title": "Publishing your add-on" + }, + "hassio_addon_repository": { + "title": "Create an add-on repository" + }, + "hassio_addon_security": { + "title": "Add-on security" + }, + "hassio_addon_testing": { + "title": "Local add-on testing" + }, + "hassio_addon_tutorial": { + "title": "Tutorial: Making your first add-on" + }, + "hassio_debugging": { + "title": "Debugging Hass.io" + }, + "hassio_hass": { + "title": "Hass.io <> Home Assistant integration development", + "sidebar_label": "HASS Integration development" + }, + "integration_quality_scale_index": { + "title": "Integration Quality Scale", + "sidebar_label": "Integration Quality Scale" + }, + "intent_builtin": { + "title": "Built-in intents" + }, + "intent_conversation": { + "title": "Registering sentences" + }, + "intent_firing": { + "title": "Firing intents" + }, + "intent_handling": { + "title": "Handling intents" + }, + "intent_index": { + "title": "Intents", + "sidebar_label": "Introduction" + }, + "internationalization_backend_localization": { + "title": "Backend Localization" + }, + "internationalization_custom_component_localization": { + "title": "Custom Component Localization" + }, + "internationalization_index": { + "title": "Internationalization" + }, + "internationalization_translation": { + "title": "Translation" + }, + "lovelace_custom_card": { + "title": "Lovelace: Custom Cards" + }, + "lovelace_index": { + "title": "Lovelace UI", + "sidebar_label": "Introduction" + }, + "maintenance": { + "title": "Maintenance" + }, + "misc": { + "title": "Miscellaneous" + }, + "releasing": { + "title": "Releasing" + }, + "version-0.72/version-0.72-architecture_components": { + "title": "Components Architecture", + "sidebar_label": "Components" + }, + "version-0.72/version-0.72-architecture_entities": { + "title": "Entity Architecture", + "sidebar_label": "Entity" + }, + "version-0.72/version-0.72-architecture_hassio": { + "title": "Hass.io Architecture", + "sidebar_label": "Hass.io" + }, + "version-0.72/version-0.72-architecture_index": { + "title": "Architecture", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-asyncio_101": { + "title": "Asyncio 101" + }, + "version-0.72/version-0.72-asyncio_categorizing_functions": { + "title": "Categorizing Functions" + }, + "version-0.72/version-0.72-asyncio_index": { + "title": "Asynchronous Programming", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-asyncio_working_with_async": { + "title": "Working with Async" + }, + "version-0.72/version-0.72-auth_api": { + "title": "Authentication API", + "sidebar_label": "API" + }, + "version-0.72/version-0.72-auth_auth_provider": { + "title": "Authentication Providers" + }, + "version-0.72/version-0.72-auth_index": { + "title": "Authentication", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-config_entries_config_flow_handler": { + "title": "Config Flow Handlers" + }, + "version-0.72/version-0.72-config_entries_index": { + "title": "Config Entries", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-configuration_yaml_index": { + "title": "Configuration.yaml", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-creating_component_code_review": { + "title": "Checklist for creating a component" + }, + "version-0.72/version-0.72-creating_component_deps_and_reqs": { + "title": "Requirements & Dependencies" + }, + "version-0.72/version-0.72-creating_component_discovery": { + "title": "Component Discovery" + }, + "version-0.72/version-0.72-creating_component_events": { + "title": "Handling events" + }, + "version-0.72/version-0.72-creating_component_generic_discovery": { + "title": "Generic Platform Discovery" + }, + "version-0.72/version-0.72-creating_component_index": { + "title": "Creating components", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-creating_component_loading": { + "title": "Loading your components" + }, + "version-0.72/version-0.72-creating_component_states": { + "title": "Handling states" + }, + "version-0.72/version-0.72-creating_platform_code_review": { + "title": "Checklist for creating a platform" + }, + "version-0.72/version-0.72-creating_platform_example_light": { + "title": "Example light platform" + }, + "version-0.72/version-0.72-creating_platform_example_sensor": { + "title": "Example sensor platform" + }, + "version-0.72/version-0.72-creating_platform_index": { + "title": "Adding support for a new platform", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-data_entry_flow_index": { + "title": "Data Entry Flow", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-dev_101_config": { + "title": "Using Config" + }, + "version-0.72/version-0.72-dev_101_events": { + "title": "Using Events" + }, + "version-0.72/version-0.72-dev_101_hass": { + "title": "Hass object" + }, + "version-0.72/version-0.72-dev_101_index": { + "title": "Development 101", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-dev_101_services": { + "title": "Using Services" + }, + "version-0.72/version-0.72-dev_101_states": { + "title": "Using States" + }, + "version-0.72/version-0.72-development_catching_up": { + "title": "Catching up with Reality" + }, + "version-0.72/version-0.72-development_checklist": { + "title": "Development Checklist" + }, + "version-0.72/version-0.72-development_environment": { + "title": "Set up Development Environment" + }, + "version-0.72/version-0.72-development_guidelines": { + "title": "Style guidelines" + }, + "version-0.72/version-0.72-development_index": { + "title": "Starting with Development", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-development_submitting": { + "title": "Submit your work" + }, + "version-0.72/version-0.72-development_testing": { + "title": "Testing your code" + }, + "version-0.72/version-0.72-development_typing": { + "title": "Adding type hints to your code" + }, + "version-0.72/version-0.72-development_validation": { + "title": "Validate the input" + }, + "version-0.72/version-0.72-entity_alarm_control_panel": { + "title": "Alarm Control Panel Entity", + "sidebar_label": "Alarm Control Panel" + }, + "version-0.72/version-0.72-entity_binary_sensor": { + "title": "Binary Sensor Entity", + "sidebar_label": "Binary Sensor" + }, + "version-0.72/version-0.72-entity_climate": { + "title": "Climate Entity", + "sidebar_label": "Climate" + }, + "version-0.72/version-0.72-entity_cover": { + "title": "Cover Entity", + "sidebar_label": "Cover" + }, + "version-0.72/version-0.72-entity_fan": { + "title": "Fan Entity", + "sidebar_label": "Fan" + }, + "version-0.72/version-0.72-entity_index": { + "title": "Entity", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-entity_light": { + "title": "Light Entity", + "sidebar_label": "Light" + }, + "version-0.72/version-0.72-entity_lock": { + "title": "Lock Entity", + "sidebar_label": "Lock" + }, + "version-0.72/version-0.72-entity_media_player": { + "title": "Media Player Entity", + "sidebar_label": "Media Player" + }, + "version-0.72/version-0.72-entity_registry_index": { + "title": "Entity Registry", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-entity_remote": { + "title": "Remote Entity", + "sidebar_label": "Remote" + }, + "version-0.72/version-0.72-entity_sensor": { + "title": "Sensor Entity", + "sidebar_label": "Sensor" + }, + "version-0.72/version-0.72-entity_switch": { + "title": "Switch Entity", + "sidebar_label": "Switch" + }, + "version-0.72/version-0.72-entity_vacuum": { + "title": "Vacuum Entity", + "sidebar_label": "Vacuum" + }, + "version-0.72/version-0.72-entity_weather": { + "title": "Weather Entity", + "sidebar_label": "Weather" + }, + "version-0.72/version-0.72-external_api_rest_python": { + "title": "REST API - Python bindings" + }, + "version-0.72/version-0.72-external_api_rest": { + "title": "REST API" + }, + "version-0.72/version-0.72-external_api_server_sent_events": { + "title": "Server-sent events" + }, + "version-0.72/version-0.72-external_api_websocket": { + "title": "WebSocket API" + }, + "version-0.72/version-0.72-frontend_add_card": { + "title": "Adding state card" + }, + "version-0.72/version-0.72-frontend_add_more_info": { + "title": "Adding more info dialogs" + }, + "version-0.72/version-0.72-frontend_add_websocket_api": { + "title": "Extending the WebSocket API" + }, + "version-0.72/version-0.72-frontend_architecture": { + "title": "Home Assistant Frontend Architecture", + "sidebar_label": "Architecture" + }, + "version-0.72/version-0.72-frontend_creating_custom_panels": { + "title": "Creating custom panels" + }, + "version-0.72/version-0.72-frontend_creating_custom_ui": { + "title": "Creating custom UI" + }, + "version-0.72/version-0.72-frontend_development": { + "title": "Frontend development", + "sidebar_label": "Development" + }, + "version-0.72/version-0.72-frontend_index": { + "title": "Home Assistant Frontend", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-hassio_addon_communication": { + "title": "Add-On Communication" + }, + "version-0.72/version-0.72-hassio_addon_config": { + "title": "Add-On Configuration" + }, + "version-0.72/version-0.72-hassio_addon_index": { + "title": "Developing an add-on", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-hassio_addon_presentation": { + "title": "Presenting your add-on" + }, + "version-0.72/version-0.72-hassio_addon_publishing": { + "title": "Publishing your add-on" + }, + "version-0.72/version-0.72-hassio_addon_repository": { + "title": "Create an add-on repository" + }, + "version-0.72/version-0.72-hassio_addon_testing": { + "title": "Local add-on testing" + }, + "version-0.72/version-0.72-hassio_addon_tutorial": { + "title": "Tutorial: Making your first add-on" + }, + "version-0.72/version-0.72-hassio_debugging": { + "title": "Debugging Hass.io" + }, + "version-0.72/version-0.72-hassio_hass": { + "title": "Hass.io <> Home Assistant integration development", + "sidebar_label": "HASS Integration development" + }, + "version-0.72/version-0.72-intent_builtin": { + "title": "Built-in intents" + }, + "version-0.72/version-0.72-intent_conversation": { + "title": "Registering sentences" + }, + "version-0.72/version-0.72-intent_firing": { + "title": "Firing intents" + }, + "version-0.72/version-0.72-intent_handling": { + "title": "Handling intents" + }, + "version-0.72/version-0.72-intent_index": { + "title": "Intents", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-internationalization_backend_localization": { + "title": "Backend Localization" + }, + "version-0.72/version-0.72-internationalization_custom_component_localization": { + "title": "Custom Component Localization" + }, + "version-0.72/version-0.72-internationalization_index": { + "title": "Internationalization" + }, + "version-0.72/version-0.72-internationalization_translation": { + "title": "Translation" + }, + "version-0.72/version-0.72-lovelace_card_types": { + "title": "Type Of Cards", + "sidebar_label": "Cards" + }, + "version-0.72/version-0.72-lovelace_custom_card": { + "title": "Custom Cards" + }, + "version-0.72/version-0.72-lovelace_index": { + "title": "Lovelace UI", + "sidebar_label": "Introduction" + }, + "version-0.72/version-0.72-maintenance": { + "title": "Maintenance" + }, + "version-0.72/version-0.72-misc": { + "title": "Miscellaneous" + }, + "version-0.72/version-0.72-releasing": { + "title": "Releasing" + }, + "version-0.73.0/version-0.73.0-auth_api": { + "title": "Authentication API", + "sidebar_label": "API" + }, + "version-0.73.0/version-0.73.0-development_guidelines": { + "title": "Style guidelines" + }, + "version-0.73.0/version-0.73.0-documentation_create_page": { + "title": "Create a new page" + }, + "version-0.73.0/version-0.73.0-documentation_index": { + "title": "Documentation" + }, + "version-0.73.0/version-0.73.0-documentation_standards": { + "title": "Standards" + }, + "version-0.73.0/version-0.73.0-frontend_development": { + "title": "Frontend development", + "sidebar_label": "Development" + }, + "version-0.73.0/version-0.73.0-hassio_addon_config": { + "title": "Add-On Configuration" + }, + "version-0.73.0/version-0.73.0-lovelace_custom_card": { + "title": "Custom Cards" + }, + "version-0.73.0/version-0.73.0-lovelace_index": { + "title": "Lovelace UI", + "sidebar_label": "Introduction" + }, + "version-0.74.0/version-0.74.0-asyncio_working_with_async": { + "title": "Working with Async" + }, + "version-0.74.0/version-0.74.0-auth_api": { + "title": "Authentication API", + "sidebar_label": "API" + }, + "version-0.74.0/version-0.74.0-entity_media_player": { + "title": "Media Player Entity", + "sidebar_label": "Media Player" + }, + "version-0.74.0/version-0.74.0-entity_vacuum": { + "title": "Vacuum Entity", + "sidebar_label": "Vacuum" + }, + "version-0.74.0/version-0.74.0-hassio_addon_tutorial": { + "title": "Tutorial: Making your first add-on" + }, + "version-0.74.0/version-0.74.0-internationalization_index": { + "title": "Internationalization" + }, + "version-0.74.0/version-0.74.0-lovelace_custom_card": { + "title": "Lovelace: Custom Cards" + }, + "version-0.76.0/version-0.76.0-auth_api": { + "title": "Authentication API", + "sidebar_label": "API" + }, + "version-0.76.0/version-0.76.0-auth_auth_provider": { + "title": "Authentication Providers" + }, + "version-0.76.0/version-0.76.0-development_environment": { + "title": "Set up Development Environment" + }, + "version-0.76.0/version-0.76.0-documentation_create_page": { + "title": "Create a new page" + }, + "version-0.76.0/version-0.76.0-documentation_standards": { + "title": "Standards" + }, + "version-0.76.0/version-0.76.0-frontend_creating_custom_panels": { + "title": "Creating custom panels" + }, + "version-0.76.0/version-0.76.0-frontend_data": { + "title": "Frontend data", + "sidebar_label": "Data" + }, + "version-0.76.0/version-0.76.0-hassio_addon_config": { + "title": "Add-On Configuration" + }, + "version-0.76.0/version-0.76.0-hassio_debugging": { + "title": "Debugging Hass.io" + }, + "version-0.77.0/version-0.77.0-auth_api": { + "title": "Authentication API", + "sidebar_label": "API" + }, + "version-0.77.0/version-0.77.0-auth_auth_module": { + "title": "Multi-factor Authentication Modules" + }, + "version-0.77.0/version-0.77.0-auth_auth_provider": { + "title": "Authentication Providers" + }, + "version-0.77.0/version-0.77.0-auth_index": { + "title": "Authentication", + "sidebar_label": "Introduction" + }, + "version-0.77.0/version-0.77.0-config_entries_config_flow_handler": { + "title": "Config Flow Handlers" + }, + "version-0.77.0/version-0.77.0-data_entry_flow_index": { + "title": "Data Entry Flow", + "sidebar_label": "Introduction" + }, + "version-0.77.0/version-0.77.0-external_api_rest_python": { + "title": "REST API - Python bindings", + "sidebar_label": "REST API - Python bindings" + }, + "version-0.77.0/version-0.77.0-frontend_data": { + "title": "Frontend data", + "sidebar_label": "Data" + }, + "version-0.78.0/version-0.78.0-asyncio_working_with_async": { + "title": "Working with Async" + }, + "version-0.78.0/version-0.78.0-auth_api": { + "title": "Authentication API", + "sidebar_label": "API" + }, + "version-0.78.0/version-0.78.0-auth_auth_module": { + "title": "Multi-factor Authentication Modules" + }, + "version-0.78.0/version-0.78.0-auth_index": { + "title": "Authentication", + "sidebar_label": "Introduction" + }, + "version-0.78.0/version-0.78.0-creating_component_code_review": { + "title": "Checklist for creating a component" + }, + "version-0.78.0/version-0.78.0-development_guidelines": { + "title": "Style guidelines" + }, + "version-0.78.0/version-0.78.0-device_registry_index": { + "title": "Device Registry", + "sidebar_label": "Introduction" + }, + "version-0.78.0/version-0.78.0-documentation_standards": { + "title": "Standards" + }, + "version-0.78.0/version-0.78.0-external_api_websocket": { + "title": "WebSocket API" + }, + "version-0.78.0/version-0.78.0-frontend_add_more_info": { + "title": "Adding more info dialogs" + }, + "version-0.78.0/version-0.78.0-frontend_external_auth": { + "title": "External Authentication" + }, + "version-0.78.0/version-0.78.0-hassio_addon_communication": { + "title": "Add-On Communication" + }, + "version-0.78.0/version-0.78.0-hassio_addon_config": { + "title": "Add-On Configuration" + }, + "version-0.78.0/version-0.78.0-hassio_addon_security": { + "title": "Add-on security" + }, + "version-0.79.0/version-0.79.0-creating_component_code_review": { + "title": "Checklist for creating a component" + }, + "version-0.79.0/version-0.79.0-creating_platform_code_review": { + "title": "Checklist for creating a platform" + }, + "version-0.79.0/version-0.79.0-development_environment": { + "title": "Set up Development Environment" + }, + "version-0.79.0/version-0.79.0-documentation_create_page": { + "title": "Create a new page" + }, + "version-0.79.0/version-0.79.0-documentation_index": { + "title": "Documentation" + }, + "version-0.79.0/version-0.79.0-hassio_addon_communication": { + "title": "Add-On Communication" + }, + "version-0.79.0/version-0.79.0-hassio_hass": { + "title": "Hass.io <> Home Assistant integration development", + "sidebar_label": "HASS Integration development" + }, + "version-0.79.0/version-0.79.0-integration_quality_scale_index": { + "title": "Integration Quality Scale", + "sidebar_label": "Introduction" + }, + "version-0.80.0/version-0.80.0-auth_index": { + "title": "Authentication", + "sidebar_label": "Introduction" + }, + "version-0.80.0/version-0.80.0-auth_permissions": { + "title": "Permissions" + }, + "version-0.80.0/version-0.80.0-development_catching_up": { + "title": "Catching up with Reality" + }, + "version-0.80.0/version-0.80.0-development_environment": { + "title": "Set up Development Environment" + }, + "version-0.80.0/version-0.80.0-development_submitting": { + "title": "Submit your work" + }, + "version-0.80.0/version-0.80.0-development_testing": { + "title": "Testing your code" + }, + "version-0.80.0/version-0.80.0-documentation_create_page": { + "title": "Create a new page" + }, + "version-0.80.0/version-0.80.0-documentation_index": { + "title": "Documentation" + }, + "version-0.80.0/version-0.80.0-documentation_standards": { + "title": "Standards" + }, + "version-0.80.0/version-0.80.0-entity_sensor": { + "title": "Sensor Entity", + "sidebar_label": "Sensor" + }, + "version-0.80.0/version-0.80.0-entity_water_heater": { + "title": "Water Heater Entity", + "sidebar_label": "Water Heater" + }, + "version-0.80.0/version-0.80.0-frontend_architecture": { + "title": "Home Assistant Frontend Architecture", + "sidebar_label": "Architecture" + }, + "version-0.80.0/version-0.80.0-hassio_addon_communication": { + "title": "Add-On Communication" + }, + "version-0.80.0/version-0.80.0-hassio_addon_config": { + "title": "Add-On Configuration" + }, + "version-0.80.0/version-0.80.0-hassio_addon_security": { + "title": "Add-on security" + }, + "version-0.80.0/version-0.80.0-hassio_debugging": { + "title": "Debugging Hass.io" + }, + "version-0.80.0/version-0.80.0-integration_quality_scale_index": { + "title": "Integration Quality Scale", + "sidebar_label": "Introduction" + }, + "version-0.81.0/version-0.81.0-asyncio_index": { + "title": "Asynchronous Programming", + "sidebar_label": "Introduction" + }, + "version-0.81.0/version-0.81.0-auth_api": { + "title": "Authentication API", + "sidebar_label": "API" + }, + "version-0.81.0/version-0.81.0-auth_auth_module": { + "title": "Multi-factor Authentication Modules" + }, + "version-0.81.0/version-0.81.0-development_index": { + "title": "Starting with Development", + "sidebar_label": "Introduction" + }, + "version-0.81.0/version-0.81.0-development_testing": { + "title": "Testing your code" + }, + "version-0.81.0/version-0.81.0-documentation_index": { + "title": "Documentation" + }, + "version-0.81.0/version-0.81.0-external_api_rest": { + "title": "REST API" + }, + "version-0.81.0/version-0.81.0-external_api_server_sent_events": { + "title": "Server-sent events" + }, + "version-0.81.0/version-0.81.0-hassio_addon_config": { + "title": "Add-On Configuration" + }, + "version-0.82.0/version-0.82.0-architecture_hassio": { + "title": "Hass.io Architecture", + "sidebar_label": "Hass.io" + }, + "version-0.82.0/version-0.82.0-asyncio_working_with_async": { + "title": "Working with Async" + }, + "version-0.82.0/version-0.82.0-auth_permissions": { + "title": "Permissions" + }, + "version-0.82.0/version-0.82.0-config_entries_index": { + "title": "Config Entries", + "sidebar_label": "Introduction" + }, + "version-0.82.0/version-0.82.0-creating_component_code_review": { + "title": "Checklist for creating a component" + }, + "version-0.82.0/version-0.82.0-creating_component_deps_and_reqs": { + "title": "Requirements & Dependencies" + }, + "version-0.82.0/version-0.82.0-creating_component_generic_discovery": { + "title": "Generic Platform Discovery" + }, + "version-0.82.0/version-0.82.0-development_checklist": { + "title": "Development Checklist" + }, + "version-0.82.0/version-0.82.0-development_guidelines": { + "title": "Style guidelines" + }, + "version-0.82.0/version-0.82.0-development_validation": { + "title": "Validate the input" + }, + "version-0.82.0/version-0.82.0-documentation_index": { + "title": "Documentation" + }, + "version-0.82.0/version-0.82.0-entity_registry_index": { + "title": "Entity Registry", + "sidebar_label": "Introduction" + }, + "version-0.82.0/version-0.82.0-entity_sensor": { + "title": "Sensor Entity", + "sidebar_label": "Sensor" + }, + "version-0.82.0/version-0.82.0-hassio_addon_config": { + "title": "Add-On Configuration" + }, + "version-0.82.0/version-0.82.0-hassio_addon_index": { + "title": "Developing an add-on", + "sidebar_label": "Introduction" + }, + "version-0.83.0/version-0.83.0-app_integration_index": { + "title": "Native App Integration", + "sidebar_label": "Introduction" + }, + "version-0.83.0/version-0.83.0-app_integration_sending_data": { + "title": "Sending data home" + }, + "version-0.83.0/version-0.83.0-app_integration_setup": { + "title": "Connecting to an instance" + }, + "version-0.83.0/version-0.83.0-app_integration_webview": { + "title": "Authenticated Webview" + }, + "version-0.83.0/version-0.83.0-auth_api": { + "title": "Authentication API", + "sidebar_label": "API" + }, + "version-0.83.0/version-0.83.0-external_api_server_sent_events": { + "title": "Server-sent events" + }, + "version-0.83.0/version-0.83.0-hassio_addon_presentation": { + "title": "Presenting your add-on" + }, + "version-0.83.0/version-0.83.0-hassio_addon_publishing": { + "title": "Publishing your add-on" + }, + "version-0.84.0/version-0.84.0-creating_component_code_review": { + "title": "Checklist for creating a component" + }, + "version-0.84.0/version-0.84.0-external_api_rest": { + "title": "REST API" + }, + "version-0.85/version-0.85-asyncio_categorizing_functions": { + "title": "Categorizing Functions" + }, + "version-0.85/version-0.85-documentation_index": { + "title": "Documentation" + }, + "version-0.85/version-0.85-entity_air_pollutants": { + "title": "Air Pollutants Entity", + "sidebar_label": "Air Pollutants" + }, + "version-0.85/version-0.85-entity_sensor": { + "title": "Sensor Entity", + "sidebar_label": "Sensor" + }, + "version-0.85/version-0.85-external_api_rest": { + "title": "REST API" + }, + "version-0.85/version-0.85-frontend_add_card": { + "title": "Adding state card" + }, + "version-0.85/version-0.85-frontend_add_more_info": { + "title": "Adding more info dialogs" + }, + "version-0.86.0/version-0.86.0-development_environment": { + "title": "Set up Development Environment" + }, + "version-0.86.0/version-0.86.0-documentation_index": { + "title": "Documentation" + }, + "version-0.86.0/version-0.86.0-entity_air_quality": { + "title": "Air Quality Entity", + "sidebar_label": "Air Quality" + }, + "version-0.86.0/version-0.86.0-external_api_rest": { + "title": "REST API" + }, + "version-0.86.0/version-0.86.0-hassio_addon_config": { + "title": "Add-On Configuration" + }, + "version-0.86.0/version-0.86.0-lovelace_custom_card": { + "title": "Lovelace: Custom Cards" + }, + "version-0.87.0/version-0.87.0-area_registry_index": { + "title": "Area Registry", + "sidebar_label": "Introduction" + }, + "version-0.87.0/version-0.87.0-development_environment": { + "title": "Set up Development Environment" + }, + "version-0.87.0/version-0.87.0-device_registry_index": { + "title": "Device Registry", + "sidebar_label": "Introduction" + }, + "version-0.87.0/version-0.87.0-documentation_create_page": { + "title": "Create a new page" + }, + "version-0.87.0/version-0.87.0-documentation_standards": { + "title": "Standards" + }, + "version-0.87.0/version-0.87.0-frontend_architecture": { + "title": "Home Assistant Frontend Architecture", + "sidebar_label": "Architecture" + }, + "version-0.87.0/version-0.87.0-frontend_development": { + "title": "Frontend development", + "sidebar_label": "Development" + }, + "version-0.88.0/version-0.88.0-development_guidelines": { + "title": "Style guidelines" + }, + "version-0.88.0/version-0.88.0-entity_index": { + "title": "Entity", + "sidebar_label": "Introduction" + }, + "version-0.88.0/version-0.88.0-frontend_development": { + "title": "Frontend development", + "sidebar_label": "Development" + }, + "version-0.88.0/version-0.88.0-lovelace_custom_card": { + "title": "Lovelace: Custom Cards" + }, + "version-0.89.0/version-0.89.0-app_integration_index": { + "title": "Native App Integration", + "sidebar_label": "Introduction" + }, + "version-0.89.0/version-0.89.0-app_integration_sending_data": { + "title": "Sending data home" + }, + "version-0.89.0/version-0.89.0-app_integration_setup": { + "title": "Connecting to an instance" + }, + "version-0.89.0/version-0.89.0-auth_auth_module": { + "title": "Multi-factor Authentication Modules" + }, + "version-0.89.0/version-0.89.0-config_entries_index": { + "title": "Config Entries", + "sidebar_label": "Introduction" + }, + "version-0.89.0/version-0.89.0-config_entries_options_flow_handler": { + "title": "Options Flow Handlers" + }, + "version-0.89.0/version-0.89.0-creating_component_code_review": { + "title": "Checklist for creating a component" + }, + "version-0.89.0/version-0.89.0-creating_platform_code_review": { + "title": "Checklist for creating a platform" + }, + "version-0.89.0/version-0.89.0-development_checklist": { + "title": "Development Checklist" + }, + "version-0.89.0/version-0.89.0-development_environment": { + "title": "Set up Development Environment" + }, + "version-0.89.0/version-0.89.0-device_registry_index": { + "title": "Device Registry", + "sidebar_label": "Introduction" + }, + "version-0.89.0/version-0.89.0-entity_alarm_control_panel": { + "title": "Alarm Control Panel Entity", + "sidebar_label": "Alarm Control Panel" + }, + "version-0.89.0/version-0.89.0-entity_cover": { + "title": "Cover Entity", + "sidebar_label": "Cover" + }, + "version-0.89.0/version-0.89.0-internationalization_translation": { + "title": "Translation" + }, + "version-0.90.0/version-0.90.0-app_integration_sending_data": { + "title": "Sending data home" + }, + "version-0.90.0/version-0.90.0-auth_permissions": { + "title": "Permissions" + }, + "version-0.90.0/version-0.90.0-config_entries_index": { + "title": "Config Entries", + "sidebar_label": "Introduction" + }, + "version-0.90.0/version-0.90.0-development_environment": { + "title": "Set up Development Environment" + }, + "version-0.90.0/version-0.90.0-device_registry_index": { + "title": "Device Registry", + "sidebar_label": "Introduction" + }, + "version-0.90.0/version-0.90.0-external_api_rest": { + "title": "REST API" + }, + "version-0.90.0/version-0.90.0-external_api_websocket": { + "title": "WebSocket API" + }, + "version-0.90.0/version-0.90.0-hassio_addon_config": { + "title": "Add-On Configuration" + }, + "version-0.90.0/version-0.90.0-hassio_addon_tutorial": { + "title": "Tutorial: Making your first add-on" + }, + "version-0.90.0/version-0.90.0-maintenance": { + "title": "Maintenance" + }, + "version-0.91.0/version-0.91.0-asyncio_working_with_async": { + "title": "Working with Async" + }, + "version-0.91.0/version-0.91.0-creating_component_code_review": { + "title": "Checklist for creating a component" + }, + "version-0.91.0/version-0.91.0-creating_platform_example_light": { + "title": "Example light platform" + }, + "version-0.91.0/version-0.91.0-creating_platform_example_sensor": { + "title": "Example sensor platform" + }, + "version-0.91.0/version-0.91.0-dev_101_events": { + "title": "Using Events" + }, + "version-0.91.0/version-0.91.0-entity_media_player": { + "title": "Media Player Entity", + "sidebar_label": "Media Player" + }, + "version-0.91.0/version-0.91.0-entity_sensor": { + "title": "Sensor Entity", + "sidebar_label": "Sensor" + }, + "version-0.91.0/version-0.91.0-integration_quality_scale_index": { + "title": "Integration Quality Scale", + "sidebar_label": "Introduction" + }, + "version-0.91.2/version-0.91.2-app_integration_notifications": { + "title": "Push Notifications" + }, + "version-0.91.2/version-0.91.2-app_integration_sending_data": { + "title": "Sending data home" + }, + "version-0.91.2/version-0.91.2-app_integration_sensors": { + "title": "Sensors" + }, + "version-0.91.2/version-0.91.2-app_integration_setup": { + "title": "Connecting to an instance" + }, + "version-0.91.2/version-0.91.2-auth_auth_module": { + "title": "Multi-factor Authentication Modules" + }, + "version-0.91.2/version-0.91.2-config_entries_config_flow_handler": { + "title": "Integration Configuration", + "sidebar_label": "Configuration" + }, + "version-0.91.2/version-0.91.2-config_entries_index": { + "title": "Config Entries", + "sidebar_label": "Introduction" + }, + "version-0.91.2/version-0.91.2-config_entries_options_flow_handler": { + "title": "Integration Configuration Options", + "sidebar_label": "Configuration Options" + }, + "version-0.91.2/version-0.91.2-creating_component_code_review": { + "title": "Checklist for creating a component", + "sidebar_label": "Component Checklist" + }, + "version-0.91.2/version-0.91.2-creating_component_deps_and_reqs": { + "title": "creating_component_deps_and_reqs" + }, + "version-0.91.2/version-0.91.2-creating_component_generic_discovery": { + "title": "Integration with Multiple Platforms", + "sidebar_label": "Multiple platforms" + }, + "version-0.91.2/version-0.91.2-creating_component_index": { + "title": "Creating a Minimal Component", + "sidebar_label": "Minimal Component" + }, + "version-0.91.2/version-0.91.2-creating_integration_file_structure": { + "title": "Integration File Structure", + "sidebar_label": "File Structure" + }, + "version-0.91.2/version-0.91.2-creating_integration_manifest": { + "title": "Integration Manifest", + "sidebar_label": "Manifest" + }, + "version-0.91.2/version-0.91.2-creating_platform_code_review": { + "title": "Checklist for creating a platform", + "sidebar_label": "Platform Checklist" + }, + "version-0.91.2/version-0.91.2-creating_platform_example_light": { + "title": "creating_platform_example_light" + }, + "version-0.91.2/version-0.91.2-creating_platform_example_sensor": { + "title": "creating_platform_example_sensor" + }, + "version-0.91.2/version-0.91.2-creating_platform_index": { + "title": "Integration Platforms", + "sidebar_label": "Platforms" + }, + "version-0.91.2/version-0.91.2-dev_101_services": { + "title": "Integration Services", + "sidebar_label": "Custom Services" + }, + "version-0.91.2/version-0.91.2-dev_101_states": { + "title": "Using States" + }, + "version-0.91.2/version-0.91.2-development_checklist": { + "title": "Development Checklist", + "sidebar_label": "Introduction" + }, + "version-0.91.2/version-0.91.2-development_guidelines": { + "title": "Style guidelines" + }, + "version-0.91.2/version-0.91.2-development_index": { + "title": "Starting with Development", + "sidebar_label": "Introduction" + }, + "version-0.91.2/version-0.91.2-development_validation": { + "title": "Validate the input" + }, + "version-0.91.2/version-0.91.2-entity_sensor": { + "title": "Sensor Entity", + "sidebar_label": "Sensor" + }, + "version-0.91.2/version-0.91.2-internationalization_translation": { + "title": "Translation" + }, + "version-0.91.2/version-0.91.2-maintenance": { + "title": "Maintenance" + }, + "version-0.92.0/version-0.92.0-app_integration_setup": { + "title": "Connecting to an instance" + }, + "version-0.92.0/version-0.92.0-auth_auth_module": { + "title": "Multi-factor Authentication Modules" + }, + "version-0.92.0/version-0.92.0-creating_integration_manifest": { + "title": "Integration Manifest", + "sidebar_label": "Manifest" + }, + "version-0.92.0/version-0.92.0-creating_platform_index": { + "title": "Integration Platforms", + "sidebar_label": "Platforms" + }, + "version-0.92.0/version-0.92.0-development_submitting": { + "title": "Submit your work" + }, + "version-0.92.0/version-0.92.0-entity_climate": { + "title": "Climate Entity", + "sidebar_label": "Climate" + }, + "version-0.92.0/version-0.92.0-entity_fan": { + "title": "Fan Entity", + "sidebar_label": "Fan" + }, + "version-0.92.0/version-0.92.0-entity_media_player": { + "title": "Media Player Entity", + "sidebar_label": "Media Player" + }, + "version-0.92.0/version-0.92.0-entity_registry_index": { + "title": "Entity Registry", + "sidebar_label": "Introduction" + }, + "version-0.92.0/version-0.92.0-external_api_websocket": { + "title": "WebSocket API" + }, + "version-0.92.0/version-0.92.0-hassio_addon_communication": { + "title": "Add-On Communication" + }, + "version-0.92.0/version-0.92.0-hassio_addon_config": { + "title": "Add-On Configuration" + }, + "version-0.92.0/version-0.92.0-hassio_addon_index": { + "title": "Developing an add-on", + "sidebar_label": "Introduction" + }, + "version-0.92.0/version-0.92.0-hassio_addon_presentation": { + "title": "Presenting your add-on" + }, + "version-0.92.0/version-0.92.0-hassio_addon_publishing": { + "title": "Publishing your add-on" + }, + "version-0.92.0/version-0.92.0-hassio_addon_security": { + "title": "Add-on security" + }, + "version-0.92.0/version-0.92.0-hassio_addon_testing": { + "title": "Local add-on testing" + }, + "version-0.92.0/version-0.92.0-hassio_debugging": { + "title": "Debugging Hass.io" + }, + "version-0.92.0/version-0.92.0-hassio_hass": { + "title": "Hass.io <> Home Assistant integration development", + "sidebar_label": "HASS Integration development" + }, + "version-0.92.1/version-0.92.1-creating_integration_manifest": { + "title": "Integration Manifest", + "sidebar_label": "Manifest" + }, + "version-0.92.1/version-0.92.1-development_checklist": { + "title": "Development Checklist", + "sidebar_label": "Introduction" + }, + "version-0.92.1/version-0.92.1-entity_fan": { + "title": "Fan Entity", + "sidebar_label": "Fan" + }, + "version-0.92.1/version-0.92.1-entity_light": { + "title": "Light Entity", + "sidebar_label": "Light" + }, + "version-0.92.1/version-0.92.1-entity_media_player": { + "title": "Media Player Entity", + "sidebar_label": "Media Player" + }, + "version-0.92.1/version-0.92.1-internationalization_custom_component_localization": { + "title": "Custom Component Localization" + }, + "version-0.93.0/version-0.93.0-auth_permissions": { + "title": "Permissions" + }, + "version-0.93.0/version-0.93.0-creating_integration_manifest": { + "title": "Integration Manifest", + "sidebar_label": "Manifest" + }, + "version-0.93.0/version-0.93.0-development_testing": { + "title": "Testing your code" + }, + "version-0.93.0/version-0.93.0-documentation_create_page": { + "title": "Create a new page" + }, + "version-0.93.0/version-0.93.0-entity_index": { + "title": "Entity", + "sidebar_label": "Introduction" + }, + "version-0.93.0/version-0.93.0-entity_media_player": { + "title": "Media Player Entity", + "sidebar_label": "Media Player" + }, + "version-0.93.0/version-0.93.0-entity_registry_index": { + "title": "Entity Registry", + "sidebar_label": "Introduction" + }, + "version-0.93.0/version-0.93.0-entity_switch": { + "title": "Switch Entity", + "sidebar_label": "Switch" + }, + "version-0.93.0/version-0.93.0-hassio_addon_index": { + "title": "Developing an add-on", + "sidebar_label": "Introduction" + }, + "version-0.93.0/version-0.93.0-hassio_addon_security": { + "title": "Add-on security" + }, + "version-0.93.0/version-0.93.0-hassio_debugging": { + "title": "Debugging Hass.io" + } + }, + "links": { + "Architecture": "Architecture", + "Frontend": "Frontend", + "Backend": "Backend", + "Misc": "Misc", + "Blog": "Blog" + }, + "categories": { + "Architecture": "Architecture", + "Entities": "Entities", + "Authentication": "Authentication", + "Config Entries": "Config Entries", + "Data Entry Flow": "Data Entry Flow", + "Entity Registry": "Entity Registry", + "Device Registry": "Device Registry", + "Area Registry": "Area Registry", + "Frontend": "Frontend", + "Extending the frontend": "Extending the frontend", + "Custom UI": "Custom UI", + "Development Workflow": "Development Workflow", + "Building Integrations": "Building Integrations", + "Development Checklist": "Development Checklist", + "Home Assistant Core 101": "Home Assistant Core 101", + "Misc": "Misc", + "Introduction": "Introduction", + "External API": "External API", + "Internationalization": "Internationalization", + "Documentation": "Documentation", + "Intents": "Intents", + "Native App Integration": "Native App Integration", + "asyncio": "asyncio", + "Hass.io": "Hass.io", + "Hass.io Add-Ons": "Hass.io Add-Ons", + "Maintainer docs": "Maintainer docs", + "Configuration.yaml": "Configuration.yaml", + "Developing a feature": "Developing a feature", + "Development 101": "Development 101", + "Integration Quality Scale": "Integration Quality Scale", + "Creating Platforms": "Creating Platforms", + "Creating Components": "Creating Components", + "Lovelace UI": "Lovelace UI" + } + }, + "pages-strings": { + "Learn more using the [documentation on this site.](/test-site/docs/en/doc1.html)|no description given": "Learn more using the [documentation on this site.](/test-site/docs/en/doc1.html)", + "Browse Docs|no description given": "Browse Docs", + "Ask questions about the documentation and project|no description given": "Ask questions about the documentation and project", + "Join the community|no description given": "Join the community", + "Find out what's new with this project|no description given": "Find out what's new with this project", + "Stay up to date|no description given": "Stay up to date", + "Need help?|no description given": "Need help?", + "This project is maintained by a dedicated group of people.|statement made to reader": "This project is maintained by a dedicated group of people.", + "Help Translate|recruit community translators for your project": "Help Translate", + "Edit this Doc|recruitment message asking to edit the doc source": "Edit", + "Translate this Doc|recruitment message asking to translate the docs": "Translate" + } +} diff --git a/website/translated_docs/ko-KR/version-0.74.0/lovelace_custom_card.md b/website/translated_docs/ko-KR/version-0.74.0/lovelace_custom_card.md new file mode 100644 index 00000000..f7f350c4 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.74.0/lovelace_custom_card.md @@ -0,0 +1,212 @@ +--- +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 +``` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.78.0/frontend_add_more_info.md b/website/translated_docs/ko-KR/version-0.78.0/frontend_add_more_info.md new file mode 100644 index 00000000..498b14af --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.78.0/frontend_add_more_info.md @@ -0,0 +1,15 @@ +--- +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.](/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.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) \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.78.0/frontend_external_auth.md b/website/translated_docs/ko-KR/version-0.78.0/frontend_external_auth.md new file mode 100644 index 00000000..21e7588f --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.78.0/frontend_external_auth.md @@ -0,0 +1,68 @@ +--- +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); +``` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.78.0/hassio_addon_communication.md b/website/translated_docs/ko-KR/version-0.78.0/hassio_addon_communication.md new file mode 100644 index 00000000..7d2fcf15 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.78.0/hassio_addon_communication.md @@ -0,0 +1,37 @@ +--- +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](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. 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](https://www.home-assistant.io/developers/websocket_api/). 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](https://github.com/home-assistant/hassio/blob/master/API.md), 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*` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.78.0/hassio_addon_config.md b/website/translated_docs/ko-KR/version-0.78.0/hassio_addon_config.md new file mode 100644 index 00000000..7816c566 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.78.0/hassio_addon_config.md @@ -0,0 +1,207 @@ +--- +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 | 설명 | +| ------------- | ------------------------------------------------------------ | +| 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" +} +``` + +| 키 | 구분 | Required | 설명 | +| ----------------- | ----------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 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" + } +} +``` + +| 키 | Required | 설명 | +| ---------- | -------- | ------------------------------------------------------------------------------------------------------ | +| 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. | \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.78.0/hassio_addon_security.md b/website/translated_docs/ko-KR/version-0.78.0/hassio_addon_security.md new file mode 100644 index 00000000..f5e31ef2 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.78.0/hassio_addon_security.md @@ -0,0 +1,33 @@ +--- +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 | 설명 | +| ------------- | ------------------------------------------------------------------------------------------------------ | +| 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 \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.79.0/creating_component_code_review.md b/website/translated_docs/ko-KR/version-0.79.0/creating_component_code_review.md new file mode 100644 index 00000000..14ae25ea --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.79.0/creating_component_code_review.md @@ -0,0 +1,49 @@ +--- +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() +``` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.79.0/creating_platform_code_review.md b/website/translated_docs/ko-KR/version-0.79.0/creating_platform_code_review.md new file mode 100644 index 00000000..4ab692a8 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.79.0/creating_platform_code_review.md @@ -0,0 +1,82 @@ +--- +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() +``` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.79.0/development_environment.md b/website/translated_docs/ko-KR/version-0.79.0/development_environment.md new file mode 100644 index 00000000..bcefdb58 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.79.0/development_environment.md @@ -0,0 +1,113 @@ +--- +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 +``` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.79.0/documentation_create_page.md b/website/translated_docs/ko-KR/version-0.79.0/documentation_create_page.md new file mode 100644 index 00000000..032112b2 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.79.0/documentation_create_page.md @@ -0,0 +1,134 @@ +--- +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. + +| 구분 | 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`. \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.79.0/documentation_index.md b/website/translated_docs/ko-KR/version-0.79.0/documentation_index.md new file mode 100644 index 00000000..5ed0d65a --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.79.0/documentation_index.md @@ -0,0 +1,37 @@ +--- +title: Documentation +id: version-0.79.0-documentation_index +original_id: documentation_index +--- + +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 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 +- 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 +``` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.79.0/hassio_addon_communication.md b/website/translated_docs/ko-KR/version-0.79.0/hassio_addon_communication.md new file mode 100644 index 00000000..e5b622b3 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.79.0/hassio_addon_communication.md @@ -0,0 +1,37 @@ +--- +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](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. 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](https://www.home-assistant.io/developers/websocket_api/). 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](https://github.com/home-assistant/hassio/blob/master/API.md), 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*` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.79.0/hassio_hass.md b/website/translated_docs/ko-KR/version-0.79.0/hassio_hass.md new file mode 100644 index 00000000..0745d752 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.79.0/hassio_hass.md @@ -0,0 +1,54 @@ +--- +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. \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.86.0/hassio_addon_config.md b/website/translated_docs/ko-KR/version-0.86.0/hassio_addon_config.md new file mode 100644 index 00000000..6f1435f2 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.86.0/hassio_addon_config.md @@ -0,0 +1,212 @@ +--- +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 | 설명 | +| ------------- | ------------------------------------------------------------ | +| 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" +} +``` + +| 키 | 구분 | Required | 설명 | +| ----------------- | ----------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 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" + } +} +``` + +| 키 | Required | 설명 | +| ---------- | -------- | ------------------------------------------------------------------------------------------------------ | +| 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. | \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.87.0/area_registry_index.md b/website/translated_docs/ko-KR/version-0.87.0/area_registry_index.md new file mode 100644 index 00000000..40a7bd0c --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.87.0/area_registry_index.md @@ -0,0 +1,13 @@ +--- +title: Area Registry +sidebar_label: 대하여 +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 | 설명 | +| --------- | ----------------------------------------------- | +| 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/ko-KR/version-0.91.2/creating_component_code_review.md b/website/translated_docs/ko-KR/version-0.91.2/creating_component_code_review.md new file mode 100644 index 00000000..5320ed64 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/creating_component_code_review.md @@ -0,0 +1,71 @@ +--- +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. \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/creating_component_deps_and_reqs.md b/website/translated_docs/ko-KR/version-0.91.2/creating_component_deps_and_reqs.md new file mode 100644 index 00000000..6f3fb119 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/creating_component_deps_and_reqs.md @@ -0,0 +1,9 @@ +--- +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/translated_docs/ko-KR/version-0.91.2/creating_component_generic_discovery.md b/website/translated_docs/ko-KR/version-0.91.2/creating_component_generic_discovery.md new file mode 100644 index 00000000..3472b025 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/creating_component_generic_discovery.md @@ -0,0 +1,22 @@ +--- +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/) \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/creating_component_index.md b/website/translated_docs/ko-KR/version-0.91.2/creating_component_index.md new file mode 100644 index 00000000..c8a6c8f5 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/creating_component_index.md @@ -0,0 +1,40 @@ +--- +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. \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/creating_integration_file_structure.md b/website/translated_docs/ko-KR/version-0.91.2/creating_integration_file_structure.md new file mode 100644 index 00000000..8cea5571 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/creating_integration_file_structure.md @@ -0,0 +1,33 @@ +--- +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. \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/creating_integration_manifest.md b/website/translated_docs/ko-KR/version-0.91.2/creating_integration_manifest.md new file mode 100644 index 00000000..864fe1bb --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/creating_integration_manifest.md @@ -0,0 +1,79 @@ +--- +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 +``` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/creating_platform_code_review.md b/website/translated_docs/ko-KR/version-0.91.2/creating_platform_code_review.md new file mode 100644 index 00000000..158a5950 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/creating_platform_code_review.md @@ -0,0 +1,95 @@ +--- +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/) \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/creating_platform_example_light.md b/website/translated_docs/ko-KR/version-0.91.2/creating_platform_example_light.md new file mode 100644 index 00000000..aedca662 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/creating_platform_example_light.md @@ -0,0 +1,9 @@ +--- +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/translated_docs/ko-KR/version-0.91.2/creating_platform_example_sensor.md b/website/translated_docs/ko-KR/version-0.91.2/creating_platform_example_sensor.md new file mode 100644 index 00000000..e4bb3da9 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/creating_platform_example_sensor.md @@ -0,0 +1,9 @@ +--- +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/translated_docs/ko-KR/version-0.91.2/creating_platform_index.md b/website/translated_docs/ko-KR/version-0.91.2/creating_platform_index.md new file mode 100644 index 00000000..829c3835 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/creating_platform_index.md @@ -0,0 +1,23 @@ +--- +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. \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/dev_101_services.md b/website/translated_docs/ko-KR/version-0.91.2/dev_101_services.md new file mode 100644 index 00000000..99736bfa --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/dev_101_services.md @@ -0,0 +1,78 @@ +--- +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' +``` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/dev_101_states.md b/website/translated_docs/ko-KR/version-0.91.2/dev_101_states.md new file mode 100644 index 00000000..a8d6aeca --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/dev_101_states.md @@ -0,0 +1,128 @@ +--- +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. \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/development_checklist.md b/website/translated_docs/ko-KR/version-0.91.2/development_checklist.md new file mode 100644 index 00000000..e253b273 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/development_checklist.md @@ -0,0 +1,17 @@ +--- +title: Development Checklist +sidebar_label: 대하여 +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. \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/development_guidelines.md b/website/translated_docs/ko-KR/version-0.91.2/development_guidelines.md new file mode 100644 index 00000000..eac417c4 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/development_guidelines.md @@ -0,0 +1,83 @@ +--- +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) +``` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/development_index.md b/website/translated_docs/ko-KR/version-0.91.2/development_index.md new file mode 100644 index 00000000..1505de78 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/development_index.md @@ -0,0 +1,12 @@ +--- +title: Starting with Development +sidebar_label: 대하여 +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/). \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/development_validation.md b/website/translated_docs/ko-KR/version-0.91.2/development_validation.md new file mode 100644 index 00000000..919e1c46 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/development_validation.md @@ -0,0 +1,82 @@ +--- +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)]), +``` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/entity_sensor.md b/website/translated_docs/ko-KR/version-0.91.2/entity_sensor.md new file mode 100644 index 00000000..0c613c55 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/entity_sensor.md @@ -0,0 +1,33 @@ +--- +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 | 구분 | Default | 설명 | +| --------------------- | ------ | ------------ | -------------------------------------------------------- | +| 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. + +| 구분 | Unit | 설명 | +| --------------- | -------- | -------------------------- | +| 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/ko-KR/version-0.91.2/internationalization_translation.md b/website/translated_docs/ko-KR/version-0.91.2/internationalization_translation.md new file mode 100644 index 00000000..361dfb8c --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/internationalization_translation.md @@ -0,0 +1,44 @@ +--- +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). \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.91.2/maintenance.md b/website/translated_docs/ko-KR/version-0.91.2/maintenance.md new file mode 100644 index 00000000..91455cf6 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.91.2/maintenance.md @@ -0,0 +1,45 @@ +--- +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. \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.92.0/app_integration_setup.md b/website/translated_docs/ko-KR/version-0.92.0/app_integration_setup.md new file mode 100644 index 00000000..989df599 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.92.0/app_integration_setup.md @@ -0,0 +1,82 @@ +--- +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](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", + } +} +``` + +| 키 | Required | 구분 | 설명 | +| --------------------- | -------- | ------ | --------------------------------------------------------------------------------------------------- | +| `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" +} +``` + +| 키 | 구분 | 설명 | +| --------------- | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `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/ko-KR/version-0.92.0/auth_auth_module.md b/website/translated_docs/ko-KR/version-0.92.0/auth_auth_module.md new file mode 100644 index 00000000..411dd20e --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.92.0/auth_auth_module.md @@ -0,0 +1,68 @@ +--- +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 | 설명 | +| ---------------------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| `@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/ko-KR/version-0.92.0/creating_integration_manifest.md b/website/translated_docs/ko-KR/version-0.92.0/creating_integration_manifest.md new file mode 100644 index 00000000..7a493716 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.92.0/creating_integration_manifest.md @@ -0,0 +1,79 @@ +--- +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 +``` \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.92.0/creating_platform_index.md b/website/translated_docs/ko-KR/version-0.92.0/creating_platform_index.md new file mode 100644 index 00000000..7569afeb --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.92.0/creating_platform_index.md @@ -0,0 +1,23 @@ +--- +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. \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.92.0/development_submitting.md b/website/translated_docs/ko-KR/version-0.92.0/development_submitting.md new file mode 100644 index 00000000..b8103bd9 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.92.0/development_submitting.md @@ -0,0 +1,43 @@ +--- +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/). \ No newline at end of file diff --git a/website/translated_docs/ko-KR/version-0.92.0/entity_climate.md b/website/translated_docs/ko-KR/version-0.92.0/entity_climate.md new file mode 100644 index 00000000..de7d33a0 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.92.0/entity_climate.md @@ -0,0 +1,232 @@ +--- +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 | 구분 | Default | 설명 | +| ------------------------- | ---------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------- | +| 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 | 설명 | +| ---------------- | ------------------------------ | +| 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 | 설명 | +| --------------------------------- | ------------------------------------------------------ | +| 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/ko-KR/version-0.92.0/entity_fan.md b/website/translated_docs/ko-KR/version-0.92.0/entity_fan.md new file mode 100644 index 00000000..d0a015e3 --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.92.0/entity_fan.md @@ -0,0 +1,89 @@ +--- +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 | 구분 | Default | 설명 | +| ------------------ | ------- | ------- | --------------------------------------- | +| 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 | 설명 | +| --------------------- | ---------------------------------------------- | +| '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/ko-KR/version-0.92.0/entity_registry_index.md b/website/translated_docs/ko-KR/version-0.92.0/entity_registry_index.md new file mode 100644 index 00000000..977a2c1e --- /dev/null +++ b/website/translated_docs/ko-KR/version-0.92.0/entity_registry_index.md @@ -0,0 +1,24 @@ +--- +title: Entity Registry +sidebar_label: 대하여 +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}`. \ No newline at end of file diff --git a/website/translated_docs/ko/app_integration_notifications.md b/website/translated_docs/ko/app_integration_notifications.md new file mode 100644 index 00000000..3029a213 --- /dev/null +++ b/website/translated_docs/ko/app_integration_notifications.md @@ -0,0 +1,235 @@ +--- +title: "푸시 알림" +--- + +`mobile_app` 컴포넌트는 별도의 외부 컴포넌트를 설치하지 않고도 푸시 알림을 사용자에게 보낼 수 있는 알림 플랫폼이 내장되어 있습니다. + +## 푸시 알림 활성화시키기 + +애플리케이션에서 알림 플랫폼을 활성화하려면, 최초 등록 또는 기존 등록을 업데이트하는 동안 `app_data` 객체에 두 개의 키를 설정해야 합니다. + +| 키 | 구분 | 설명 | +| ------------ | ------ | -------------------------------------------------------------- | +| `push_token` | string | 사용자 기기의 고유한 푸시 알림 토큰 예를 들어 APNS 토큰이나 FCM 인스턴스 ID/토큰이 될 수 있습니다. | +| `push_url` | string | 푸시 알림이 HTTP POSTed 될 서버의 URL 주소. | + +이러한 키를 설정 한 후에는 알림 대상을 인식 할 수 있도록 Home Assistant 를 다시 시작하도록 사용자에게 알려주어야 합니다. 형식은 `notify.mobile_app_` 입니다. + +## 서버 컴포넌트 배치하기 + +알림 플랫폼은 사용자에게 알리는 방법을 가리지 않습니다. 단순히 실제 요청을 처리하는 외부 서버로 알림을 전달할 뿐입니다. 이러한 접근방식은 푸시 알림 인프라를 완전하게 제어할 수 있도록 해줍니다. + +Firebase Cloud Functions 와 Firebase Cloud Messaging 을 사용하는 푸시 알림 전달자의 서버 구현 예제는 이 문서의 다음 섹션을 참조해주세요. + +서버는 다음과 같이 HTTP POST 페이로드를 받을수 있어야 합니다. + +```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" + } +} +``` + +알림이 성공적으로 전달 대기중인 것으로 가정 할 경우 201 상태 코드로 응답해야 합니다. + +### 오류 관련 사항들 + +만약 오류가 발생하면 상태 코드 201 또는 429 *이외의* 오류에 대한 설명을 반환해야합니다. 오류 응답은 JSON 객체여야하며 다음 키 중 하나를 포함 할 수 있습니다: + +| 키 | 구분 | 설명 | +| -------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------ | +| `errorMessage` | string | 제공된 경우 미리 설정된 오류 메시지에 추가됩니다. 예를 들어, `errorMessage`가 "Apple 과 통신할 수 없습니다" 라면, "내부 서버 오류입니다. 나중에 다시 시도해주세요: 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" + } +} +``` + +| 키 | 구분 | 설명 | +| ------------ | ----------------- | ------------------------------------------------------------------------------------------------ | +| `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/nl/app_integration_index.md b/website/translated_docs/nl/app_integration_index.md new file mode 100644 index 00000000..8a181840 --- /dev/null +++ b/website/translated_docs/nl/app_integration_index.md @@ -0,0 +1,11 @@ +--- +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/nl/app_integration_notifications.md b/website/translated_docs/nl/app_integration_notifications.md new file mode 100644 index 00000000..a4861554 --- /dev/null +++ b/website/translated_docs/nl/app_integration_notifications.md @@ -0,0 +1,235 @@ +--- +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/nl/app_integration_sending_data.md b/website/translated_docs/nl/app_integration_sending_data.md new file mode 100644 index 00000000..eebab867 --- /dev/null +++ b/website/translated_docs/nl/app_integration_sending_data.md @@ -0,0 +1,228 @@ +--- +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/nl/app_integration_sensors.md b/website/translated_docs/nl/app_integration_sensors.md new file mode 100644 index 00000000..08a30ce9 --- /dev/null +++ b/website/translated_docs/nl/app_integration_sensors.md @@ -0,0 +1,77 @@ +--- +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/nl/app_integration_setup.md b/website/translated_docs/nl/app_integration_setup.md new file mode 100644 index 00000000..efd3a03b --- /dev/null +++ b/website/translated_docs/nl/app_integration_setup.md @@ -0,0 +1,80 @@ +--- +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/nl/app_integration_webview.md b/website/translated_docs/nl/app_integration_webview.md new file mode 100644 index 00000000..82bc53d8 --- /dev/null +++ b/website/translated_docs/nl/app_integration_webview.md @@ -0,0 +1,9 @@ +--- +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/nl/architecture_components.md b/website/translated_docs/nl/architecture_components.md new file mode 100644 index 00000000..a1031012 --- /dev/null +++ b/website/translated_docs/nl/architecture_components.md @@ -0,0 +1,50 @@ +--- +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/nl/architecture_entities.md b/website/translated_docs/nl/architecture_entities.md new file mode 100644 index 00000000..82535365 --- /dev/null +++ b/website/translated_docs/nl/architecture_entities.md @@ -0,0 +1,41 @@ +--- +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/nl/architecture_hassio.md b/website/translated_docs/nl/architecture_hassio.md new file mode 100644 index 00000000..df33383a --- /dev/null +++ b/website/translated_docs/nl/architecture_hassio.md @@ -0,0 +1,26 @@ +--- +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/nl/architecture_index.md b/website/translated_docs/nl/architecture_index.md new file mode 100644 index 00000000..550a818d --- /dev/null +++ b/website/translated_docs/nl/architecture_index.md @@ -0,0 +1,23 @@ +--- +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/nl/area_registry_index.md b/website/translated_docs/nl/area_registry_index.md new file mode 100644 index 00000000..faf0d208 --- /dev/null +++ b/website/translated_docs/nl/area_registry_index.md @@ -0,0 +1,11 @@ +--- +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/nl/asyncio_101.md b/website/translated_docs/nl/asyncio_101.md new file mode 100644 index 00000000..3ffc7dd7 --- /dev/null +++ b/website/translated_docs/nl/asyncio_101.md @@ -0,0 +1,9 @@ +--- +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/nl/asyncio_categorizing_functions.md b/website/translated_docs/nl/asyncio_categorizing_functions.md new file mode 100644 index 00000000..71e8206d --- /dev/null +++ b/website/translated_docs/nl/asyncio_categorizing_functions.md @@ -0,0 +1,67 @@ +--- +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 new file mode 100644 index 00000000..6dd2ecaa --- /dev/null +++ b/website/translated_docs/nl/asyncio_index.md @@ -0,0 +1,16 @@ +--- +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 new file mode 100644 index 00000000..6f56876c --- /dev/null +++ b/website/translated_docs/nl/asyncio_working_with_async.md @@ -0,0 +1,102 @@ +--- +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 new file mode 100644 index 00000000..0fa664fa --- /dev/null +++ b/website/translated_docs/nl/auth_api.md @@ -0,0 +1,245 @@ +--- +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 new file mode 100644 index 00000000..e0e000a7 --- /dev/null +++ b/website/translated_docs/nl/auth_auth_module.md @@ -0,0 +1,66 @@ +--- +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 new file mode 100644 index 00000000..b652973d --- /dev/null +++ b/website/translated_docs/nl/auth_auth_provider.md @@ -0,0 +1,42 @@ +--- +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 new file mode 100644 index 00000000..695e6c7d --- /dev/null +++ b/website/translated_docs/nl/auth_index.md @@ -0,0 +1,50 @@ +--- +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 new file mode 100644 index 00000000..9aed470e --- /dev/null +++ b/website/translated_docs/nl/auth_permissions.md @@ -0,0 +1,266 @@ +--- +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 new file mode 100644 index 00000000..6fe750d0 --- /dev/null +++ b/website/translated_docs/nl/config_entries_config_flow_handler.md @@ -0,0 +1,91 @@ +--- +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 new file mode 100644 index 00000000..2416509c --- /dev/null +++ b/website/translated_docs/nl/config_entries_index.md @@ -0,0 +1,166 @@ +--- +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 new file mode 100644 index 00000000..03be7419 --- /dev/null +++ b/website/translated_docs/nl/config_entries_options_flow_handler.md @@ -0,0 +1,44 @@ +--- +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 new file mode 100644 index 00000000..15f42083 --- /dev/null +++ b/website/translated_docs/nl/configuration_yaml_index.md @@ -0,0 +1,57 @@ +--- +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 new file mode 100644 index 00000000..2a87cc44 --- /dev/null +++ b/website/translated_docs/nl/creating_component_code_review.md @@ -0,0 +1,69 @@ +--- +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 new file mode 100644 index 00000000..c7826476 --- /dev/null +++ b/website/translated_docs/nl/creating_component_deps_and_reqs.md @@ -0,0 +1,7 @@ +--- +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 new file mode 100644 index 00000000..cf5fc3a1 --- /dev/null +++ b/website/translated_docs/nl/creating_component_generic_discovery.md @@ -0,0 +1,20 @@ +--- +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 new file mode 100644 index 00000000..9f02858f --- /dev/null +++ b/website/translated_docs/nl/creating_component_index.md @@ -0,0 +1,38 @@ +--- +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 new file mode 100644 index 00000000..3a535d07 --- /dev/null +++ b/website/translated_docs/nl/creating_integration_file_structure.md @@ -0,0 +1,31 @@ +--- +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 new file mode 100644 index 00000000..7c76a6d7 --- /dev/null +++ b/website/translated_docs/nl/creating_integration_manifest.md @@ -0,0 +1,77 @@ +--- +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 new file mode 100644 index 00000000..a7609f74 --- /dev/null +++ b/website/translated_docs/nl/creating_platform_code_review.md @@ -0,0 +1,93 @@ +--- +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 new file mode 100644 index 00000000..2eb9bdbd --- /dev/null +++ b/website/translated_docs/nl/creating_platform_example_light.md @@ -0,0 +1,7 @@ +--- +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 new file mode 100644 index 00000000..97d1683d --- /dev/null +++ b/website/translated_docs/nl/creating_platform_example_sensor.md @@ -0,0 +1,7 @@ +--- +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 new file mode 100644 index 00000000..4a8cab3f --- /dev/null +++ b/website/translated_docs/nl/creating_platform_index.md @@ -0,0 +1,21 @@ +--- +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 new file mode 100644 index 00000000..bd2e3b20 --- /dev/null +++ b/website/translated_docs/nl/data_entry_flow_index.md @@ -0,0 +1,223 @@ +--- +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 new file mode 100644 index 00000000..e91e5f31 --- /dev/null +++ b/website/translated_docs/nl/dev_101_config.md @@ -0,0 +1,28 @@ +--- +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 new file mode 100644 index 00000000..f6f38462 --- /dev/null +++ b/website/translated_docs/nl/dev_101_events.md @@ -0,0 +1,58 @@ +--- +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 new file mode 100644 index 00000000..bc8d414e --- /dev/null +++ b/website/translated_docs/nl/dev_101_hass.md @@ -0,0 +1,30 @@ +--- +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 new file mode 100644 index 00000000..9cbf54d8 --- /dev/null +++ b/website/translated_docs/nl/dev_101_index.md @@ -0,0 +1,44 @@ +--- +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 new file mode 100644 index 00000000..7bae113c --- /dev/null +++ b/website/translated_docs/nl/dev_101_services.md @@ -0,0 +1,76 @@ +--- +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 new file mode 100644 index 00000000..d35379c7 --- /dev/null +++ b/website/translated_docs/nl/dev_101_states.md @@ -0,0 +1,126 @@ +--- +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 new file mode 100644 index 00000000..7f14f6d5 --- /dev/null +++ b/website/translated_docs/nl/development_catching_up.md @@ -0,0 +1,35 @@ +--- +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 new file mode 100644 index 00000000..0d1652cd --- /dev/null +++ b/website/translated_docs/nl/development_checklist.md @@ -0,0 +1,14 @@ +--- +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 new file mode 100644 index 00000000..9e0bc03c --- /dev/null +++ b/website/translated_docs/nl/development_environment.md @@ -0,0 +1,117 @@ +--- +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 new file mode 100644 index 00000000..0383618a --- /dev/null +++ b/website/translated_docs/nl/development_guidelines.md @@ -0,0 +1,81 @@ +--- +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 new file mode 100644 index 00000000..d0557fd3 --- /dev/null +++ b/website/translated_docs/nl/development_index.md @@ -0,0 +1,10 @@ +--- +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 new file mode 100644 index 00000000..5f0bac56 --- /dev/null +++ b/website/translated_docs/nl/development_submitting.md @@ -0,0 +1,41 @@ +--- +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 new file mode 100644 index 00000000..2b57f7e1 --- /dev/null +++ b/website/translated_docs/nl/development_testing.md @@ -0,0 +1,79 @@ +--- +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 new file mode 100644 index 00000000..81f153cd --- /dev/null +++ b/website/translated_docs/nl/development_typing.md @@ -0,0 +1,23 @@ +--- +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 new file mode 100644 index 00000000..9e7770a7 --- /dev/null +++ b/website/translated_docs/nl/development_validation.md @@ -0,0 +1,80 @@ +--- +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 new file mode 100644 index 00000000..394002ea --- /dev/null +++ b/website/translated_docs/nl/device_registry_index.md @@ -0,0 +1,80 @@ +--- +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 new file mode 100644 index 00000000..e1669a55 --- /dev/null +++ b/website/translated_docs/nl/documentation_create_page.md @@ -0,0 +1,132 @@ +--- +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 new file mode 100644 index 00000000..d196169c --- /dev/null +++ b/website/translated_docs/nl/documentation_index.md @@ -0,0 +1,52 @@ +--- +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 new file mode 100644 index 00000000..d0ae54d1 --- /dev/null +++ b/website/translated_docs/nl/documentation_standards.md @@ -0,0 +1,122 @@ +--- +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 new file mode 100644 index 00000000..81c10f5c --- /dev/null +++ b/website/translated_docs/nl/entity_air_quality.md @@ -0,0 +1,25 @@ +--- +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 new file mode 100644 index 00000000..9dc91192 --- /dev/null +++ b/website/translated_docs/nl/entity_alarm_control_panel.md @@ -0,0 +1,130 @@ +--- +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 new file mode 100644 index 00000000..1a791ddb --- /dev/null +++ b/website/translated_docs/nl/entity_binary_sensor.md @@ -0,0 +1,43 @@ +--- +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 new file mode 100644 index 00000000..477e1bcd --- /dev/null +++ b/website/translated_docs/nl/entity_climate.md @@ -0,0 +1,230 @@ +--- +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 new file mode 100644 index 00000000..9fe8a9ce --- /dev/null +++ b/website/translated_docs/nl/entity_cover.md @@ -0,0 +1,188 @@ +--- +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 new file mode 100644 index 00000000..27b6f7dc --- /dev/null +++ b/website/translated_docs/nl/entity_fan.md @@ -0,0 +1,87 @@ +--- +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 new file mode 100644 index 00000000..5385e078 --- /dev/null +++ b/website/translated_docs/nl/entity_index.md @@ -0,0 +1,102 @@ +--- +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 new file mode 100644 index 00000000..1b3d6561 --- /dev/null +++ b/website/translated_docs/nl/entity_light.md @@ -0,0 +1,61 @@ +--- +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 new file mode 100644 index 00000000..7983db21 --- /dev/null +++ b/website/translated_docs/nl/entity_lock.md @@ -0,0 +1,16 @@ +--- +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 new file mode 100644 index 00000000..ab327f05 --- /dev/null +++ b/website/translated_docs/nl/entity_media_player.md @@ -0,0 +1,84 @@ +--- +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 new file mode 100644 index 00000000..aa346829 --- /dev/null +++ b/website/translated_docs/nl/entity_registry_index.md @@ -0,0 +1,22 @@ +--- +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 new file mode 100644 index 00000000..b4a0251d --- /dev/null +++ b/website/translated_docs/nl/entity_remote.md @@ -0,0 +1,16 @@ +--- +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 new file mode 100644 index 00000000..6a7e6307 --- /dev/null +++ b/website/translated_docs/nl/entity_sensor.md @@ -0,0 +1,31 @@ +--- +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 new file mode 100644 index 00000000..14039422 --- /dev/null +++ b/website/translated_docs/nl/entity_switch.md @@ -0,0 +1,72 @@ +--- +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 new file mode 100644 index 00000000..b947d3df --- /dev/null +++ b/website/translated_docs/nl/entity_vacuum.md @@ -0,0 +1,63 @@ +--- +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 new file mode 100644 index 00000000..b4a13e29 --- /dev/null +++ b/website/translated_docs/nl/entity_water_heater.md @@ -0,0 +1,51 @@ +--- +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 new file mode 100644 index 00000000..b92ccbe6 --- /dev/null +++ b/website/translated_docs/nl/entity_weather.md @@ -0,0 +1,55 @@ +--- +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 new file mode 100644 index 00000000..965aae96 --- /dev/null +++ b/website/translated_docs/nl/external_api_rest.md @@ -0,0 +1,530 @@ +--- +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 new file mode 100644 index 00000000..3d415b76 --- /dev/null +++ b/website/translated_docs/nl/external_api_rest_python.md @@ -0,0 +1,7 @@ +--- +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 new file mode 100644 index 00000000..676494c3 --- /dev/null +++ b/website/translated_docs/nl/external_api_server_sent_events.md @@ -0,0 +1,72 @@ +--- +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 new file mode 100644 index 00000000..f194c309 --- /dev/null +++ b/website/translated_docs/nl/external_api_websocket.md @@ -0,0 +1,434 @@ +--- +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 new file mode 100644 index 00000000..5958da27 --- /dev/null +++ b/website/translated_docs/nl/frontend_add_card.md @@ -0,0 +1,21 @@ +--- +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 new file mode 100644 index 00000000..56519938 --- /dev/null +++ b/website/translated_docs/nl/frontend_add_more_info.md @@ -0,0 +1,13 @@ +--- +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 new file mode 100644 index 00000000..a4861554 --- /dev/null +++ b/website/translated_docs/no-NO/app_integration_notifications.md @@ -0,0 +1,235 @@ +--- +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 new file mode 100644 index 00000000..08a30ce9 --- /dev/null +++ b/website/translated_docs/no-NO/app_integration_sensors.md @@ -0,0 +1,77 @@ +--- +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 new file mode 100644 index 00000000..efd3a03b --- /dev/null +++ b/website/translated_docs/no-NO/app_integration_setup.md @@ -0,0 +1,80 @@ +--- +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 new file mode 100644 index 00000000..82bc53d8 --- /dev/null +++ b/website/translated_docs/no-NO/app_integration_webview.md @@ -0,0 +1,9 @@ +--- +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 new file mode 100644 index 00000000..a1031012 --- /dev/null +++ b/website/translated_docs/no-NO/architecture_components.md @@ -0,0 +1,50 @@ +--- +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 new file mode 100644 index 00000000..82535365 --- /dev/null +++ b/website/translated_docs/no-NO/architecture_entities.md @@ -0,0 +1,41 @@ +--- +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 new file mode 100644 index 00000000..df33383a --- /dev/null +++ b/website/translated_docs/no-NO/architecture_hassio.md @@ -0,0 +1,26 @@ +--- +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 new file mode 100644 index 00000000..550a818d --- /dev/null +++ b/website/translated_docs/no-NO/architecture_index.md @@ -0,0 +1,23 @@ +--- +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 new file mode 100644 index 00000000..faf0d208 --- /dev/null +++ b/website/translated_docs/no-NO/area_registry_index.md @@ -0,0 +1,11 @@ +--- +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 new file mode 100644 index 00000000..3ffc7dd7 --- /dev/null +++ b/website/translated_docs/no-NO/asyncio_101.md @@ -0,0 +1,9 @@ +--- +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 new file mode 100644 index 00000000..71e8206d --- /dev/null +++ b/website/translated_docs/no-NO/asyncio_categorizing_functions.md @@ -0,0 +1,67 @@ +--- +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 new file mode 100644 index 00000000..6dd2ecaa --- /dev/null +++ b/website/translated_docs/no-NO/asyncio_index.md @@ -0,0 +1,16 @@ +--- +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 new file mode 100644 index 00000000..6f56876c --- /dev/null +++ b/website/translated_docs/no-NO/asyncio_working_with_async.md @@ -0,0 +1,102 @@ +--- +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 new file mode 100644 index 00000000..0fa664fa --- /dev/null +++ b/website/translated_docs/no-NO/auth_api.md @@ -0,0 +1,245 @@ +--- +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 new file mode 100644 index 00000000..e0e000a7 --- /dev/null +++ b/website/translated_docs/no-NO/auth_auth_module.md @@ -0,0 +1,66 @@ +--- +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 new file mode 100644 index 00000000..b652973d --- /dev/null +++ b/website/translated_docs/no-NO/auth_auth_provider.md @@ -0,0 +1,42 @@ +--- +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 new file mode 100644 index 00000000..695e6c7d --- /dev/null +++ b/website/translated_docs/no-NO/auth_index.md @@ -0,0 +1,50 @@ +--- +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 new file mode 100644 index 00000000..9aed470e --- /dev/null +++ b/website/translated_docs/no-NO/auth_permissions.md @@ -0,0 +1,266 @@ +--- +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 new file mode 100644 index 00000000..6fe750d0 --- /dev/null +++ b/website/translated_docs/no-NO/config_entries_config_flow_handler.md @@ -0,0 +1,91 @@ +--- +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 new file mode 100644 index 00000000..2416509c --- /dev/null +++ b/website/translated_docs/no-NO/config_entries_index.md @@ -0,0 +1,166 @@ +--- +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 new file mode 100644 index 00000000..9f02858f --- /dev/null +++ b/website/translated_docs/no-NO/creating_component_index.md @@ -0,0 +1,38 @@ +--- +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 new file mode 100644 index 00000000..3a535d07 --- /dev/null +++ b/website/translated_docs/no-NO/creating_integration_file_structure.md @@ -0,0 +1,31 @@ +--- +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 new file mode 100644 index 00000000..7c76a6d7 --- /dev/null +++ b/website/translated_docs/no-NO/creating_integration_manifest.md @@ -0,0 +1,77 @@ +--- +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 new file mode 100644 index 00000000..a7609f74 --- /dev/null +++ b/website/translated_docs/no-NO/creating_platform_code_review.md @@ -0,0 +1,93 @@ +--- +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 new file mode 100644 index 00000000..2eb9bdbd --- /dev/null +++ b/website/translated_docs/no-NO/creating_platform_example_light.md @@ -0,0 +1,7 @@ +--- +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 new file mode 100644 index 00000000..97d1683d --- /dev/null +++ b/website/translated_docs/no-NO/creating_platform_example_sensor.md @@ -0,0 +1,7 @@ +--- +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 new file mode 100644 index 00000000..4a8cab3f --- /dev/null +++ b/website/translated_docs/no-NO/creating_platform_index.md @@ -0,0 +1,21 @@ +--- +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 new file mode 100644 index 00000000..bd2e3b20 --- /dev/null +++ b/website/translated_docs/no-NO/data_entry_flow_index.md @@ -0,0 +1,223 @@ +--- +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 new file mode 100644 index 00000000..e91e5f31 --- /dev/null +++ b/website/translated_docs/no-NO/dev_101_config.md @@ -0,0 +1,28 @@ +--- +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 new file mode 100644 index 00000000..f6f38462 --- /dev/null +++ b/website/translated_docs/no-NO/dev_101_events.md @@ -0,0 +1,58 @@ +--- +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 new file mode 100644 index 00000000..bc8d414e --- /dev/null +++ b/website/translated_docs/no-NO/dev_101_hass.md @@ -0,0 +1,30 @@ +--- +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 new file mode 100644 index 00000000..9cbf54d8 --- /dev/null +++ b/website/translated_docs/no-NO/dev_101_index.md @@ -0,0 +1,44 @@ +--- +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 new file mode 100644 index 00000000..7bae113c --- /dev/null +++ b/website/translated_docs/no-NO/dev_101_services.md @@ -0,0 +1,76 @@ +--- +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 new file mode 100644 index 00000000..d35379c7 --- /dev/null +++ b/website/translated_docs/no-NO/dev_101_states.md @@ -0,0 +1,126 @@ +--- +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 new file mode 100644 index 00000000..7f14f6d5 --- /dev/null +++ b/website/translated_docs/no-NO/development_catching_up.md @@ -0,0 +1,35 @@ +--- +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 new file mode 100644 index 00000000..0d1652cd --- /dev/null +++ b/website/translated_docs/no-NO/development_checklist.md @@ -0,0 +1,14 @@ +--- +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 new file mode 100644 index 00000000..9e0bc03c --- /dev/null +++ b/website/translated_docs/no-NO/development_environment.md @@ -0,0 +1,117 @@ +--- +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 new file mode 100644 index 00000000..0383618a --- /dev/null +++ b/website/translated_docs/no-NO/development_guidelines.md @@ -0,0 +1,81 @@ +--- +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 new file mode 100644 index 00000000..d0557fd3 --- /dev/null +++ b/website/translated_docs/no-NO/development_index.md @@ -0,0 +1,10 @@ +--- +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 new file mode 100644 index 00000000..5f0bac56 --- /dev/null +++ b/website/translated_docs/no-NO/development_submitting.md @@ -0,0 +1,41 @@ +--- +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 new file mode 100644 index 00000000..2b57f7e1 --- /dev/null +++ b/website/translated_docs/no-NO/development_testing.md @@ -0,0 +1,79 @@ +--- +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 new file mode 100644 index 00000000..81f153cd --- /dev/null +++ b/website/translated_docs/no-NO/development_typing.md @@ -0,0 +1,23 @@ +--- +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 new file mode 100644 index 00000000..9e7770a7 --- /dev/null +++ b/website/translated_docs/no-NO/development_validation.md @@ -0,0 +1,80 @@ +--- +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 new file mode 100644 index 00000000..394002ea --- /dev/null +++ b/website/translated_docs/no-NO/device_registry_index.md @@ -0,0 +1,80 @@ +--- +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 new file mode 100644 index 00000000..e1669a55 --- /dev/null +++ b/website/translated_docs/no-NO/documentation_create_page.md @@ -0,0 +1,132 @@ +--- +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 new file mode 100644 index 00000000..d196169c --- /dev/null +++ b/website/translated_docs/no-NO/documentation_index.md @@ -0,0 +1,52 @@ +--- +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 new file mode 100644 index 00000000..d0ae54d1 --- /dev/null +++ b/website/translated_docs/no-NO/documentation_standards.md @@ -0,0 +1,122 @@ +--- +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 new file mode 100644 index 00000000..81c10f5c --- /dev/null +++ b/website/translated_docs/no-NO/entity_air_quality.md @@ -0,0 +1,25 @@ +--- +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 new file mode 100644 index 00000000..9dc91192 --- /dev/null +++ b/website/translated_docs/no-NO/entity_alarm_control_panel.md @@ -0,0 +1,130 @@ +--- +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 new file mode 100644 index 00000000..1a791ddb --- /dev/null +++ b/website/translated_docs/no-NO/entity_binary_sensor.md @@ -0,0 +1,43 @@ +--- +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 new file mode 100644 index 00000000..477e1bcd --- /dev/null +++ b/website/translated_docs/no-NO/entity_climate.md @@ -0,0 +1,230 @@ +--- +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 new file mode 100644 index 00000000..9fe8a9ce --- /dev/null +++ b/website/translated_docs/no-NO/entity_cover.md @@ -0,0 +1,188 @@ +--- +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 new file mode 100644 index 00000000..27b6f7dc --- /dev/null +++ b/website/translated_docs/no-NO/entity_fan.md @@ -0,0 +1,87 @@ +--- +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 new file mode 100644 index 00000000..5385e078 --- /dev/null +++ b/website/translated_docs/no-NO/entity_index.md @@ -0,0 +1,102 @@ +--- +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 new file mode 100644 index 00000000..1b3d6561 --- /dev/null +++ b/website/translated_docs/no-NO/entity_light.md @@ -0,0 +1,61 @@ +--- +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 new file mode 100644 index 00000000..7983db21 --- /dev/null +++ b/website/translated_docs/no-NO/entity_lock.md @@ -0,0 +1,16 @@ +--- +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 new file mode 100644 index 00000000..ab327f05 --- /dev/null +++ b/website/translated_docs/no-NO/entity_media_player.md @@ -0,0 +1,84 @@ +--- +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 new file mode 100644 index 00000000..aa346829 --- /dev/null +++ b/website/translated_docs/no-NO/entity_registry_index.md @@ -0,0 +1,22 @@ +--- +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 new file mode 100644 index 00000000..b4a0251d --- /dev/null +++ b/website/translated_docs/no-NO/entity_remote.md @@ -0,0 +1,16 @@ +--- +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 new file mode 100644 index 00000000..6a7e6307 --- /dev/null +++ b/website/translated_docs/no-NO/entity_sensor.md @@ -0,0 +1,31 @@ +--- +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 new file mode 100644 index 00000000..14039422 --- /dev/null +++ b/website/translated_docs/no-NO/entity_switch.md @@ -0,0 +1,72 @@ +--- +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 new file mode 100644 index 00000000..b947d3df --- /dev/null +++ b/website/translated_docs/no-NO/entity_vacuum.md @@ -0,0 +1,63 @@ +--- +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 new file mode 100644 index 00000000..b4a13e29 --- /dev/null +++ b/website/translated_docs/no-NO/entity_water_heater.md @@ -0,0 +1,51 @@ +--- +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 new file mode 100644 index 00000000..b92ccbe6 --- /dev/null +++ b/website/translated_docs/no-NO/entity_weather.md @@ -0,0 +1,55 @@ +--- +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 new file mode 100644 index 00000000..965aae96 --- /dev/null +++ b/website/translated_docs/no-NO/external_api_rest.md @@ -0,0 +1,530 @@ +--- +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 new file mode 100644 index 00000000..3d415b76 --- /dev/null +++ b/website/translated_docs/no-NO/external_api_rest_python.md @@ -0,0 +1,7 @@ +--- +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 new file mode 100644 index 00000000..676494c3 --- /dev/null +++ b/website/translated_docs/no-NO/external_api_server_sent_events.md @@ -0,0 +1,72 @@ +--- +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 new file mode 100644 index 00000000..f194c309 --- /dev/null +++ b/website/translated_docs/no-NO/external_api_websocket.md @@ -0,0 +1,434 @@ +--- +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 new file mode 100644 index 00000000..5958da27 --- /dev/null +++ b/website/translated_docs/no-NO/frontend_add_card.md @@ -0,0 +1,21 @@ +--- +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 new file mode 100644 index 00000000..56519938 --- /dev/null +++ b/website/translated_docs/no-NO/frontend_add_more_info.md @@ -0,0 +1,13 @@ +--- +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 new file mode 100644 index 00000000..77e8f5a1 --- /dev/null +++ b/website/translated_docs/no-NO/frontend_add_websocket_api.md @@ -0,0 +1,129 @@ +--- +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 new file mode 100644 index 00000000..b2be6753 --- /dev/null +++ b/website/translated_docs/no-NO/frontend_architecture.md @@ -0,0 +1,60 @@ +--- +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 new file mode 100644 index 00000000..7b57e82b --- /dev/null +++ b/website/translated_docs/no-NO/frontend_creating_custom_panels.md @@ -0,0 +1,42 @@ +--- +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 new file mode 100644 index 00000000..41cfc105 --- /dev/null +++ b/website/translated_docs/no-NO/frontend_creating_custom_ui.md @@ -0,0 +1,118 @@ +--- +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 new file mode 100644 index 00000000..7d3b6c6e --- /dev/null +++ b/website/translated_docs/no-NO/frontend_data.md @@ -0,0 +1,137 @@ +--- +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 new file mode 100644 index 00000000..c810c8c4 --- /dev/null +++ b/website/translated_docs/no-NO/frontend_development.md @@ -0,0 +1,103 @@ +--- +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 +``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/frontend_external_auth.md b/website/translated_docs/no-NO/frontend_external_auth.md new file mode 100644 index 00000000..b23f6c1b --- /dev/null +++ b/website/translated_docs/no-NO/frontend_external_auth.md @@ -0,0 +1,66 @@ +--- +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 new file mode 100644 index 00000000..66fccc8e --- /dev/null +++ b/website/translated_docs/no-NO/frontend_index.md @@ -0,0 +1,10 @@ +--- +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 new file mode 100644 index 00000000..a7615dae --- /dev/null +++ b/website/translated_docs/no-NO/hassio_addon_communication.md @@ -0,0 +1,39 @@ +--- +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 new file mode 100644 index 00000000..2a2caa6f --- /dev/null +++ b/website/translated_docs/no-NO/hassio_addon_config.md @@ -0,0 +1,222 @@ +--- +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 new file mode 100644 index 00000000..8b786a49 --- /dev/null +++ b/website/translated_docs/no-NO/hassio_addon_index.md @@ -0,0 +1,28 @@ +--- +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 new file mode 100644 index 00000000..889e8b31 --- /dev/null +++ b/website/translated_docs/no-NO/hassio_addon_presentation.md @@ -0,0 +1,63 @@ +--- +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 new file mode 100644 index 00000000..38b48bac --- /dev/null +++ b/website/translated_docs/no-NO/hassio_addon_publishing.md @@ -0,0 +1,56 @@ +--- +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 new file mode 100644 index 00000000..8ad68672 --- /dev/null +++ b/website/translated_docs/no-NO/hassio_addon_repository.md @@ -0,0 +1,29 @@ +--- +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 new file mode 100644 index 00000000..d012a5fb --- /dev/null +++ b/website/translated_docs/no-NO/hassio_addon_security.md @@ -0,0 +1,38 @@ +--- +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 new file mode 100644 index 00000000..2d089763 --- /dev/null +++ b/website/translated_docs/no-NO/hassio_addon_testing.md @@ -0,0 +1,28 @@ +--- +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 new file mode 100644 index 00000000..7d90afee --- /dev/null +++ b/website/translated_docs/no-NO/hassio_addon_tutorial.md @@ -0,0 +1,179 @@ +--- +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 new file mode 100644 index 00000000..0ec57a76 --- /dev/null +++ b/website/translated_docs/no-NO/hassio_debugging.md @@ -0,0 +1,82 @@ +--- +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 new file mode 100644 index 00000000..d9c33baf --- /dev/null +++ b/website/translated_docs/no-NO/hassio_hass.md @@ -0,0 +1,58 @@ +--- +title: "Hass.io <> Home Assistant integration development" +sidebar_label: "HASS 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 new file mode 100644 index 00000000..03c552a1 --- /dev/null +++ b/website/translated_docs/no-NO/integration_quality_scale_index.md @@ -0,0 +1,54 @@ +--- +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 new file mode 100644 index 00000000..9ea35895 --- /dev/null +++ b/website/translated_docs/no-NO/intent_builtin.md @@ -0,0 +1,77 @@ +--- +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 new file mode 100644 index 00000000..e80639ec --- /dev/null +++ b/website/translated_docs/no-NO/intent_conversation.md @@ -0,0 +1,19 @@ +--- +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 new file mode 100644 index 00000000..e46e3c7e --- /dev/null +++ b/website/translated_docs/no-NO/intent_firing.md @@ -0,0 +1,52 @@ +--- +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 new file mode 100644 index 00000000..dc06e4e0 --- /dev/null +++ b/website/translated_docs/no-NO/intent_handling.md @@ -0,0 +1,42 @@ +--- +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 new file mode 100644 index 00000000..0e055c9f --- /dev/null +++ b/website/translated_docs/no-NO/intent_index.md @@ -0,0 +1,33 @@ +--- +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 new file mode 100644 index 00000000..53ffb2c8 --- /dev/null +++ b/website/translated_docs/no-NO/internationalization_backend_localization.md @@ -0,0 +1,46 @@ +--- +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 new file mode 100644 index 00000000..da2dc8c1 --- /dev/null +++ b/website/translated_docs/no-NO/internationalization_custom_component_localization.md @@ -0,0 +1,13 @@ +--- +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 new file mode 100644 index 00000000..615e351b --- /dev/null +++ b/website/translated_docs/no-NO/internationalization_index.md @@ -0,0 +1,11 @@ +--- +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 new file mode 100644 index 00000000..a6faf7c9 --- /dev/null +++ b/website/translated_docs/no-NO/internationalization_translation.md @@ -0,0 +1,42 @@ +--- +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 new file mode 100644 index 00000000..fdf5c707 --- /dev/null +++ b/website/translated_docs/no-NO/lovelace_custom_card.md @@ -0,0 +1,225 @@ +--- +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 +``` \ No newline at end of file diff --git a/website/translated_docs/no-NO/lovelace_index.md b/website/translated_docs/no-NO/lovelace_index.md new file mode 100644 index 00000000..40c4e67d --- /dev/null +++ b/website/translated_docs/no-NO/lovelace_index.md @@ -0,0 +1,8 @@ +--- +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 new file mode 100644 index 00000000..78b94aac --- /dev/null +++ b/website/translated_docs/no-NO/maintenance.md @@ -0,0 +1,43 @@ +--- +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 new file mode 100644 index 00000000..925d2868 --- /dev/null +++ b/website/translated_docs/no-NO/misc.md @@ -0,0 +1,5 @@ +--- +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 new file mode 100644 index 00000000..dc56665b --- /dev/null +++ b/website/translated_docs/no-NO/releasing.md @@ -0,0 +1,67 @@ +--- +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 new file mode 100644 index 00000000..8a181840 --- /dev/null +++ b/website/translated_docs/pl/app_integration_index.md @@ -0,0 +1,11 @@ +--- +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 new file mode 100644 index 00000000..a4861554 --- /dev/null +++ b/website/translated_docs/pl/app_integration_notifications.md @@ -0,0 +1,235 @@ +--- +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 new file mode 100644 index 00000000..eebab867 --- /dev/null +++ b/website/translated_docs/pl/app_integration_sending_data.md @@ -0,0 +1,228 @@ +--- +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 new file mode 100644 index 00000000..08a30ce9 --- /dev/null +++ b/website/translated_docs/pl/app_integration_sensors.md @@ -0,0 +1,77 @@ +--- +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 new file mode 100644 index 00000000..efd3a03b --- /dev/null +++ b/website/translated_docs/pl/app_integration_setup.md @@ -0,0 +1,80 @@ +--- +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 new file mode 100644 index 00000000..82bc53d8 --- /dev/null +++ b/website/translated_docs/pl/app_integration_webview.md @@ -0,0 +1,9 @@ +--- +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 new file mode 100644 index 00000000..a1031012 --- /dev/null +++ b/website/translated_docs/pl/architecture_components.md @@ -0,0 +1,50 @@ +--- +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 new file mode 100644 index 00000000..82535365 --- /dev/null +++ b/website/translated_docs/pl/architecture_entities.md @@ -0,0 +1,41 @@ +--- +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 new file mode 100644 index 00000000..df33383a --- /dev/null +++ b/website/translated_docs/pl/architecture_hassio.md @@ -0,0 +1,26 @@ +--- +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 new file mode 100644 index 00000000..550a818d --- /dev/null +++ b/website/translated_docs/pl/architecture_index.md @@ -0,0 +1,23 @@ +--- +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 new file mode 100644 index 00000000..faf0d208 --- /dev/null +++ b/website/translated_docs/pl/area_registry_index.md @@ -0,0 +1,11 @@ +--- +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 new file mode 100644 index 00000000..3ffc7dd7 --- /dev/null +++ b/website/translated_docs/pl/asyncio_101.md @@ -0,0 +1,9 @@ +--- +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 new file mode 100644 index 00000000..71e8206d --- /dev/null +++ b/website/translated_docs/pl/asyncio_categorizing_functions.md @@ -0,0 +1,67 @@ +--- +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 new file mode 100644 index 00000000..6dd2ecaa --- /dev/null +++ b/website/translated_docs/pl/asyncio_index.md @@ -0,0 +1,16 @@ +--- +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 new file mode 100644 index 00000000..6f56876c --- /dev/null +++ b/website/translated_docs/pl/asyncio_working_with_async.md @@ -0,0 +1,102 @@ +--- +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 new file mode 100644 index 00000000..0fa664fa --- /dev/null +++ b/website/translated_docs/pl/auth_api.md @@ -0,0 +1,245 @@ +--- +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 new file mode 100644 index 00000000..e0e000a7 --- /dev/null +++ b/website/translated_docs/pl/auth_auth_module.md @@ -0,0 +1,66 @@ +--- +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 new file mode 100644 index 00000000..b652973d --- /dev/null +++ b/website/translated_docs/pl/auth_auth_provider.md @@ -0,0 +1,42 @@ +--- +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 new file mode 100644 index 00000000..695e6c7d --- /dev/null +++ b/website/translated_docs/pl/auth_index.md @@ -0,0 +1,50 @@ +--- +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 new file mode 100644 index 00000000..9aed470e --- /dev/null +++ b/website/translated_docs/pl/auth_permissions.md @@ -0,0 +1,266 @@ +--- +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 new file mode 100644 index 00000000..6fe750d0 --- /dev/null +++ b/website/translated_docs/pl/config_entries_config_flow_handler.md @@ -0,0 +1,91 @@ +--- +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 new file mode 100644 index 00000000..2416509c --- /dev/null +++ b/website/translated_docs/pl/config_entries_index.md @@ -0,0 +1,166 @@ +--- +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 new file mode 100644 index 00000000..03be7419 --- /dev/null +++ b/website/translated_docs/pl/config_entries_options_flow_handler.md @@ -0,0 +1,44 @@ +--- +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 new file mode 100644 index 00000000..15f42083 --- /dev/null +++ b/website/translated_docs/pl/configuration_yaml_index.md @@ -0,0 +1,57 @@ +--- +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 new file mode 100644 index 00000000..2a87cc44 --- /dev/null +++ b/website/translated_docs/pl/creating_component_code_review.md @@ -0,0 +1,69 @@ +--- +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 new file mode 100644 index 00000000..c7826476 --- /dev/null +++ b/website/translated_docs/pl/creating_component_deps_and_reqs.md @@ -0,0 +1,7 @@ +--- +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 new file mode 100644 index 00000000..cf5fc3a1 --- /dev/null +++ b/website/translated_docs/pl/creating_component_generic_discovery.md @@ -0,0 +1,20 @@ +--- +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 new file mode 100644 index 00000000..9f02858f --- /dev/null +++ b/website/translated_docs/pl/creating_component_index.md @@ -0,0 +1,38 @@ +--- +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 new file mode 100644 index 00000000..3a535d07 --- /dev/null +++ b/website/translated_docs/pl/creating_integration_file_structure.md @@ -0,0 +1,31 @@ +--- +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 new file mode 100644 index 00000000..7c76a6d7 --- /dev/null +++ b/website/translated_docs/pl/creating_integration_manifest.md @@ -0,0 +1,77 @@ +--- +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 new file mode 100644 index 00000000..a7609f74 --- /dev/null +++ b/website/translated_docs/pl/creating_platform_code_review.md @@ -0,0 +1,93 @@ +--- +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 new file mode 100644 index 00000000..2eb9bdbd --- /dev/null +++ b/website/translated_docs/pl/creating_platform_example_light.md @@ -0,0 +1,7 @@ +--- +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 new file mode 100644 index 00000000..97d1683d --- /dev/null +++ b/website/translated_docs/pl/creating_platform_example_sensor.md @@ -0,0 +1,7 @@ +--- +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 new file mode 100644 index 00000000..4a8cab3f --- /dev/null +++ b/website/translated_docs/pl/creating_platform_index.md @@ -0,0 +1,21 @@ +--- +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 new file mode 100644 index 00000000..bd2e3b20 --- /dev/null +++ b/website/translated_docs/pl/data_entry_flow_index.md @@ -0,0 +1,223 @@ +--- +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 new file mode 100644 index 00000000..e91e5f31 --- /dev/null +++ b/website/translated_docs/pl/dev_101_config.md @@ -0,0 +1,28 @@ +--- +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 new file mode 100644 index 00000000..f6f38462 --- /dev/null +++ b/website/translated_docs/pl/dev_101_events.md @@ -0,0 +1,58 @@ +--- +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 new file mode 100644 index 00000000..bc8d414e --- /dev/null +++ b/website/translated_docs/pl/dev_101_hass.md @@ -0,0 +1,30 @@ +--- +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 new file mode 100644 index 00000000..9cbf54d8 --- /dev/null +++ b/website/translated_docs/pl/dev_101_index.md @@ -0,0 +1,44 @@ +--- +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 new file mode 100644 index 00000000..7bae113c --- /dev/null +++ b/website/translated_docs/pl/dev_101_services.md @@ -0,0 +1,76 @@ +--- +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 new file mode 100644 index 00000000..d35379c7 --- /dev/null +++ b/website/translated_docs/pl/dev_101_states.md @@ -0,0 +1,126 @@ +--- +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 new file mode 100644 index 00000000..7f14f6d5 --- /dev/null +++ b/website/translated_docs/pl/development_catching_up.md @@ -0,0 +1,35 @@ +--- +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 new file mode 100644 index 00000000..0d1652cd --- /dev/null +++ b/website/translated_docs/pl/development_checklist.md @@ -0,0 +1,14 @@ +--- +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 new file mode 100644 index 00000000..9e0bc03c --- /dev/null +++ b/website/translated_docs/pl/development_environment.md @@ -0,0 +1,117 @@ +--- +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 new file mode 100644 index 00000000..0383618a --- /dev/null +++ b/website/translated_docs/pl/development_guidelines.md @@ -0,0 +1,81 @@ +--- +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 new file mode 100644 index 00000000..d0557fd3 --- /dev/null +++ b/website/translated_docs/pl/development_index.md @@ -0,0 +1,10 @@ +--- +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 new file mode 100644 index 00000000..5f0bac56 --- /dev/null +++ b/website/translated_docs/pl/development_submitting.md @@ -0,0 +1,41 @@ +--- +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 new file mode 100644 index 00000000..2b57f7e1 --- /dev/null +++ b/website/translated_docs/pl/development_testing.md @@ -0,0 +1,79 @@ +--- +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 new file mode 100644 index 00000000..81f153cd --- /dev/null +++ b/website/translated_docs/pl/development_typing.md @@ -0,0 +1,23 @@ +--- +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 new file mode 100644 index 00000000..9e7770a7 --- /dev/null +++ b/website/translated_docs/pl/development_validation.md @@ -0,0 +1,80 @@ +--- +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 new file mode 100644 index 00000000..394002ea --- /dev/null +++ b/website/translated_docs/pl/device_registry_index.md @@ -0,0 +1,80 @@ +--- +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 new file mode 100644 index 00000000..e1669a55 --- /dev/null +++ b/website/translated_docs/pl/documentation_create_page.md @@ -0,0 +1,132 @@ +--- +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 new file mode 100644 index 00000000..d196169c --- /dev/null +++ b/website/translated_docs/pl/documentation_index.md @@ -0,0 +1,52 @@ +--- +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 new file mode 100644 index 00000000..d0ae54d1 --- /dev/null +++ b/website/translated_docs/pl/documentation_standards.md @@ -0,0 +1,122 @@ +--- +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 new file mode 100644 index 00000000..81c10f5c --- /dev/null +++ b/website/translated_docs/pl/entity_air_quality.md @@ -0,0 +1,25 @@ +--- +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 new file mode 100644 index 00000000..9dc91192 --- /dev/null +++ b/website/translated_docs/pl/entity_alarm_control_panel.md @@ -0,0 +1,130 @@ +--- +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 new file mode 100644 index 00000000..1a791ddb --- /dev/null +++ b/website/translated_docs/pl/entity_binary_sensor.md @@ -0,0 +1,43 @@ +--- +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 new file mode 100644 index 00000000..477e1bcd --- /dev/null +++ b/website/translated_docs/pl/entity_climate.md @@ -0,0 +1,230 @@ +--- +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 new file mode 100644 index 00000000..9fe8a9ce --- /dev/null +++ b/website/translated_docs/pl/entity_cover.md @@ -0,0 +1,188 @@ +--- +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 new file mode 100644 index 00000000..27b6f7dc --- /dev/null +++ b/website/translated_docs/pl/entity_fan.md @@ -0,0 +1,87 @@ +--- +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 new file mode 100644 index 00000000..5385e078 --- /dev/null +++ b/website/translated_docs/pl/entity_index.md @@ -0,0 +1,102 @@ +--- +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 new file mode 100644 index 00000000..1b3d6561 --- /dev/null +++ b/website/translated_docs/pl/entity_light.md @@ -0,0 +1,61 @@ +--- +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 new file mode 100644 index 00000000..7983db21 --- /dev/null +++ b/website/translated_docs/pl/entity_lock.md @@ -0,0 +1,16 @@ +--- +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 new file mode 100644 index 00000000..ab327f05 --- /dev/null +++ b/website/translated_docs/pl/entity_media_player.md @@ -0,0 +1,84 @@ +--- +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 new file mode 100644 index 00000000..aa346829 --- /dev/null +++ b/website/translated_docs/pl/entity_registry_index.md @@ -0,0 +1,22 @@ +--- +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 new file mode 100644 index 00000000..b4a0251d --- /dev/null +++ b/website/translated_docs/pl/entity_remote.md @@ -0,0 +1,16 @@ +--- +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 new file mode 100644 index 00000000..6a7e6307 --- /dev/null +++ b/website/translated_docs/pl/entity_sensor.md @@ -0,0 +1,31 @@ +--- +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 new file mode 100644 index 00000000..14039422 --- /dev/null +++ b/website/translated_docs/pl/entity_switch.md @@ -0,0 +1,72 @@ +--- +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 new file mode 100644 index 00000000..b947d3df --- /dev/null +++ b/website/translated_docs/pl/entity_vacuum.md @@ -0,0 +1,63 @@ +--- +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 new file mode 100644 index 00000000..b4a13e29 --- /dev/null +++ b/website/translated_docs/pl/entity_water_heater.md @@ -0,0 +1,51 @@ +--- +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 new file mode 100644 index 00000000..b92ccbe6 --- /dev/null +++ b/website/translated_docs/pl/entity_weather.md @@ -0,0 +1,55 @@ +--- +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 new file mode 100644 index 00000000..965aae96 --- /dev/null +++ b/website/translated_docs/pl/external_api_rest.md @@ -0,0 +1,530 @@ +--- +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 new file mode 100644 index 00000000..3d415b76 --- /dev/null +++ b/website/translated_docs/pl/external_api_rest_python.md @@ -0,0 +1,7 @@ +--- +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 new file mode 100644 index 00000000..676494c3 --- /dev/null +++ b/website/translated_docs/pl/external_api_server_sent_events.md @@ -0,0 +1,72 @@ +--- +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 new file mode 100644 index 00000000..f194c309 --- /dev/null +++ b/website/translated_docs/pl/external_api_websocket.md @@ -0,0 +1,434 @@ +--- +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 new file mode 100644 index 00000000..5958da27 --- /dev/null +++ b/website/translated_docs/pl/frontend_add_card.md @@ -0,0 +1,21 @@ +--- +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