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