version bump to 0.93.0

This commit is contained in:
Paulus Schoutsen 2019-05-16 09:09:42 +02:00
parent e84638c9b5
commit cddbd976ac
13 changed files with 1046 additions and 0 deletions

View File

@ -1429,6 +1429,45 @@
},
"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": {

View File

@ -0,0 +1,273 @@
---
title: Permissions
id: version-0.93.0-auth_permissions
original_id: auth_permissions
---
> This is an experimental feature that is not enabled or enforced yet
Permissions limit the things a user has access to or can control. Permissions are attached to groups, of which a user can be a member. The combined permissions of all groups a user is a member of decides what a user can and cannot see or control.
Permissions do not apply to the user that is flagged as "owner". This user will always have access to everything.
## General permission structure
Policies are dictionaries that at the root level consist of different categories of permissions. In the current implementation this is limited to just entities.
```python
{
"entities": …
}
```
Each category can further split into subcategories that describe parts of that category.
```python
{
"entities": {
"domains": …,
"entity_ids": …
}
}
```
If a category is omitted, the user will not have permission to that category.
When defining a policy, any dictionary value at any place can be replaced with `True` or `None`. `True` means that permission is granted and `None` means use default, which is deny access.
## Entities
Entity permissions can be set on a per entity and per domain basis using the subcategories `entity_ids`, `device_ids`, `area_ids` and `domains`. You can either grant all access by setting the value to `True`, or you can specify each entity individually using the "read", "control", "edit" permissions.
The system will return the first matching result, based on the order: `entity_ids`, `device_ids`, `area_ids`, `domains`, `all`.
```json
{
"entities": {
"domains": {
"switch": true
},
"entity_ids": {
"light.kitchen": {
"read": true,
"control": true
}
}
}
}
```
## Merging policies
If a user is a member of multiple groups, the groups permission policies will be combined into a single policy at runtime. When merging policies, we will look at each level of the dictionary and compare the values for each source using the following methodology:
1. If any of the values is `True`, the merged value becomes `True`.
2. If any value is a dictionary, the merged value becomes a dictionary created by recursively checking each value using this methodology.
3. If all values are `None`, the merged value becomes `None`.
Let's look at an example:
```python
{
"entities": {
"entity_ids": {
"light.kitchen": True
}
}
}
```
```python
{
"entities": {
"entity_ids": True
}
}
```
Once merged becomes
```python
{
"entities": {
"entity_ids": True
}
}
```
## Checking permissions
We currently have two different permission checks: can the user do the read/control/edit operation on an entity, and is the user an admin and thus allowed to change this configuration setting.
Certain APIs will always be accessible to all users, but might offer a limited scope based on the permissions, like rendering a template.
### Checking permissions
To check a permission, you will need to have access to the user object. Once you have the user object, checking the permission is easy.
```python
from homeassistant.exceptions import Unauthorized
from homeasistant.permissions.const import (
POLICY_READ, POLICY_CONTROL, POLICY_EDIT
)
# Raise error if user is not an admin
if not user.is_admin:
raise Unauthorized()
# Raise error if user does not have access to control an entity
# Available policies: POLICY_READ, POLICY_CONTROL, POLICY_EDIT
if not user.permissions.check_entity(entity_id, POLICY_CONTROL):
raise Unauthorized()
```
### The context object
All service calls, fired events and states in Home Assistant have a context object. This object allows us to attribute changes to events and services. These context objects also contain a user id, which is used for checking the permissions.
It's crucial for permission checking that actions taken on behalf of the user are done with a context containing the user ID. If you are in a service handler, you should re-use the incoming context `call.context`. If you are inside a WebSocket API or Rest API endpoint, you should create a context with the correct user:
```python
from homeassistant.core import Context
await hass.services.async_call('homeassistant', 'stop', context=Context(
user_id=user.id
), blocking=True)
```
### If a permission check fails
When you detect an anauthorized action, you should raise the `homeassistant.exceptions.Unauthorized` exception. This exception will cancel the current action and notifies the user that their action is unauthorized.
The `Unauthorized` exception has various parameters, to identify the permission check that failed. All fields are optional.
| # Not all actions have an ID (like adding config entry)
| # We then use this fallback to know what category was unauth
| Parameter | Description
| --------- | -----------
| context | The context of the current call.
| user_id | The user ID that we tried to operate on.
| entity_id | The entity ID that we tried to operate on.
| config_entry_id | The config entry ID that we tried to operate on.
| perm_category | The permission category that we tested. Only necessary if we don't have an object ID that the user tried to operate on (like when we create a config entry).
| permission | The permission that we tested, ie `POLICY_READ`.
### Securing a service call handler
Service calls allow a user to control entities or with the integration as a whole. A service call uses the attached context to see which user invoked the command. Because context is used, it is important that you also pass the call context to all service calls.
All services that are registered via the entity component (`component.async_register_entity_service()`) will automatically have their permissions checked.
#### Checking entity permissions
Your service call handler will need to check the permissions for each entity that it will act on.
```python
from homeassistant.exceptions import Unauthorized, UnknownUser
from homeassistant.auth.permissions.const import POLICY_CONTROL
async def handle_entity_service(call):
"""Handle a service call."""
entity_ids = call.data['entity_id']
for entity_id in entity_ids:
if call.context.user_id:
user = await hass.auth.async_get_user(call.context.user_id)
if user is None:
raise UnknownUser(
context=call.context,
entity_id=entity_id,
permission=POLICY_CONTROL,
)
if not user.permissions.check_entity(entity_id, POLICY_CONTROL):
raise Unauthorized(
context=call.context,
entity_id=entity_id,
permission=POLICY_CONTROL,
)
# Do action on entity
async def async_setup(hass, config):
hass.services.async_register(DOMAIN, 'my_service', handle_entity_service)
return True
```
#### Checking admin permission
Starting Home Assistant 0.90, there is a special decorator to help protect
services that require admin access.
```python
# New in Home Assistant 0.90
async def handle_admin_service(call):
"""Handle a service call."""
# Do admin action
async def async_setup(hass, config):
hass.helpers.service.async_register_admin_service(
DOMAIN, 'my_service', handle_admin_service, vol.Schema({})
)
return True
```
### Securing a REST API endpoint
```python
from homeassistant.core import Context
from homeassistant.components.http.view import HomeAssistantView
from homeassistant.exceptions import Unauthorized
class MyView(HomeAssistantView):
"""View to handle Status requests."""
url = '/api/my-component/my-api'
name = 'api:my-component:my-api'
async def post(self, request):
"""Notify that the API is running."""
hass = request.app['hass']
user = request['hass_user']
if not user.is_admin:
raise Unauthorized()
hass.bus.async_fire('my-component-api-running', context=Context(
user_id=user.id
))
return self.json_message("Done.")
```
### Securing a Websocket API endpoint
Verifying permissions in a Websocket API endpoint can be done by accessing the
user via `connection.user`. If you need to check admin access, you can use the
built-in `@require_admin` decorator.
```python
from homeassistant.compnents import websocket_api
async def async_setup(hass, config):
hass.components.websocket_api.async_register_command(websocket_create)
return True
@websocket_api.require_admin
@websocket_api.async_response
@websocket_api.websocket_command({
vol.Required('type'): 'my-component/my-action',
})
async def websocket_create(hass, connection, msg):
"""Create a user."""
# Do action
```

View File

@ -0,0 +1,79 @@
---
title: Integration Manifest
sidebar_label: Manifest
id: version-0.93.0-creating_integration_manifest
original_id: creating_integration_manifest
---
Since 0.92.0, every integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, except for custom components.
```json
{
"domain": "hue",
"name": "Philips Hue",
"documentation": "https://www.home-assistant.io/components/hue",
"dependencies": ["mqtt"],
"codeowners": ["@balloob"],
"requirements": ["aiohue==1.9.1"]
}
```
Or a minimal example that you can copy into your project:
```json
{
"domain": "your_domain_name",
"name": "Your Integration",
"documentation": "https://www.example.com",
"dependencies": [],
"codeowners": [],
"requirements": []
}
```
## Domain
The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`.
## Name
The name of the integration.
## Documentation
The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/<domain>`
## 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
```

View File

@ -0,0 +1,80 @@
---
title: Testing your code
id: version-0.93.0-development_testing
original_id: development_testing
---
As it states in the [Style guidelines section](development_guidelines.md) all code is checked to verify the following:
- All the unit tests pass
- All code passes the checks from the linting tools
Local testing is done using Tox, which has been installed as part of running `script/setup` in the [virtual environment](development_environment.md). To start the tests, activate the virtual environment and simply run the command:
```bash
$ tox
```
**Important:** Run `tox` before you create your pull request to avoid annoying fixes.
Running Tox will run unit tests against the locally available Pythons, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one tox target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py36` runs unit tests only on Python 3.6.
Tox uses virtual environments under the hood to create isolated testing environments. The tox virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell Tox to recreate the virtual environments.
OSX users may see an `Error creating virtualenv` when runnng `tox`. If this occurs, install the [tox-venv](https://pypi.org/project/tox-venv/) package using the command `pip install tox-venv` and try again.
### Adding new dependencies to test environment
If you are working on tests for a component or platform and you need the dependencies available inside the Tox environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments.
### Running single tests using Tox
You can pass arguments via Tox to py.test to be able to run single test suites or test files. Replace `py36` with the Python version that you use.
```bash
# Stop after the first test fails
$ tox -e py36 -- tests/test_core.py -x
# Run test with specified name
$ tox -e py36 -- tests/test_core.py -k test_split_entity_id
# Fail a test after it runs for 2 seconds
$ tox -e py36 -- tests/test_core.py --timeout 2
# Show the 10 slowest tests
$ tox -e py36 -- tests/test_core.py --duration=10
```
### Testing outside of Tox
Running tox will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without Tox, you'll need to install the test dependencies into your Python environment:
```bash
$ pip3 install -r requirements_test_all.txt -c homeassistant/package_constraints.txt
```
Now that you have all test dependencies installed, you can run tests on individual files:
```bash
$ flake8 homeassistant/core.py
$ pylint homeassistant/core.py
$ pydocstyle homeassistant/core.py
$ py.test tests/test_core.py
```
You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script:
```bash
$ script/lint
```
### Preventing Linter Errors
Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them!
```bash
$ pip3 install flake8 flake8-docstrings
$ flake8 --install-hook=git
```
The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8.
### Notes on PyLint and PEP8 validation
If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member.

View File

@ -0,0 +1,133 @@
---
title: Create a new page
id: version-0.93.0-documentation_create_page
original_id: documentation_create_page
---
For a platform or component page, the fastest way is to make a copy of an existing page and edit it. The [Component overview](https://www.home-assistant.io/components/) and the [Examples section](https://www.home-assistant.io/cookbook/) are generated automatically, so there is no need to add a link to those pages.
Please honor the [Standards](documentation_standards.md) we have for the documentation.
If you start from scratch with a page, you need to add a header. Different sections of the documentation may need different headers.
```text
---
layout: page
title: "Awesome Sensor"
description: "home-assistant.io web presence"
date: 2015-06-17 08:00
sidebar: true
comments: false
sharing: true
footer: true
ha_release: "0.38"
ha_category: Sensor
ha_iot_class: "Local Polling"
ha_qa_scale: silver
---
Content... Written in markdown.
### {% linkable_title Linkable Header %}
...
```
Please keep in mind that if the `date:` entry is in the future then the page will not show up.
Additional keys for the file header:
- `logo`: Please check the separate section below.
- `ha_release`: The release when the integration was included, e.g., "0.38". If the current release is 0.37, make `ha_release` 0.38. If it's 0.30 or 0.40 please quote it with `" "`.
- `ha_category`: This entry is used to group the integration on the [Components overview](https://www.home-assistant.io/components/).
- `ha_iot_class`: [IoT class](https://www.home-assistant.io/blog/2016/02/12/classifying-the-internet-of-things) is the classifier for the device's behavior.
- `ha_qa_scale`: [Quality scale](https://www.home-assistant.io/docs/quality_scale/) is the representation of the integration's quality.
There are [pre-defined variables](https://jekyllrb.com/docs/variables/) available but usually, it's not necessary to use them when writing documentation.
A couple of points to remember:
- Document the needed steps to retrieve API keys or access token for the third party service or device if needed.
- Add screenshots to support the user where it makes sense.
- Add the type of the device(s) (incl. firmware) you have tested when you know that there are multiple out there.
### Configuration
Every platform page should contain a configuration sample. This sample must contain only the **required** variables to make it easy to copy and paste it for users into their `configuration.yaml` file.
The **Configuration Variables** section must use the `{% configuration %} ... {% endconfiguration %}` tag.
```text
{% configuration %}
api_key:
description: The API key to access the service.
required: true
type: string
name:
description: Name to use in the frontend.
required: false
default: The default name to use in the frontend.
type: string
monitored_conditions:
description: Conditions to display in the frontend.
required: true
type: map
keys:
weather:
description: A human-readable text summary.
temperature:
description: The current temperature.
{% endconfiguration %}
```
Available keys:
- **`description:`**: That the variable is about.
- **`required:`**: If the variable is required.
```text
required: true #=> Required
required: false #=> Optional
required: inclusive #=> Inclusive
required: exclusive #=> Exclusive
required: any string here #=> Any string here
```
- **`type:`**: The type of the variable. Allowed entries: `boolean`, `string`, `integer`, `float`, `time`, `template`, `device_class`, `icon` or `map`/`list` (for a list of entries). For multiple possibilities use `[string, integer]`. If you use `map`/`list` then should define `keys:` (see the [`template` sensor](https://www.home-assistant.io/components/sensor.template/) for an example). If you use `boolean`, then `default:` must be defined.
- **`default:`**: The default value for the variable.
### Embedding Code
You can use the [default markdown syntax](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet#code) to generate syntax highlighted code. For inline code wrap your code in back-ticks.
When you're writing code that is to be executed on the terminal, prefix it with `$`.
### Templates
For the [configuration templating](https://www.home-assistant.io/docs/configuration/templating/) [Jinja](http://jinja.pocoo.org/) is used. Check the [Documentation Standards](documentation_standards.md) for further details.
If you are don't escape templates then they will be rendered and appear blank on the website.
### HTML
The direct usage of HTML is supported but not recommended. The note boxes are an exception.
```html
<p class='note warning'>
You need to enable telnet on your router.
</p>
```
### 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`.

View File

@ -0,0 +1,104 @@
---
title: Entity
sidebar_label: Introduction
id: version-0.93.0-entity_index
original_id: entity_index
---
Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating.
Below is an example switch entity that keeps track of their state in memory.
```python
from homeassistant.components.switch import SwitchDevice
class MySwitch(SwitchDevice):
def __init__(self):
self._is_on = False
@property
def name(self):
"""Name of the device."""
return 'My Switch'
@property
def is_on(self):
"""If the switch is currently on or off."""
return self._is_on
def turn_on(self, **kwargs):
"""Turn the switch on."""
self._is_on = True
def turn_off(self, **kwargs):
"""Turn the switch off."""
self._is_on = False
```
That's all there is to it to build a switch entity! Continue reading to learn more or check out the [video tutorial](https://youtu.be/Cfasc9EgbMU?t=737).
## Updating the entity
An entity represents a device. There are various strategies to keep your entity in sync with the state of the device, the most popular one being polling.
### Polling
With polling, Home Assistant will ask the entity from time to time (depending on the update interval of the component) to fetch the latest state. Home Assistant will poll an entity when the `should_poll` property returns `True` (the default value). You can either implement your update logic using `update()` or the async method `async_update()`. This method should fetch the latest state from the device and store it in an instance variable for the properties to return it.
### Subscribing to updates
When you subscribe to updates, your code is responsible for letting Home Assistant know that an update is available. Make sure you have the `should_poll` property return `False`.
Whenever you receive new state from your subscription, you can tell Home Assistant that an update is available by calling `schedule_update_ha_state()` or async callback `async_schedule_update_ha_state()`. Pass in the boolean `True` to the method if you want Home Assistant to call your update method before writing the update to Home Assistant.
## Generic properties
The entity base class has a few properties that are common among all entities in Home Assistant. These can be added to any entity regardless of the type. All these properties are optional and don't need to be implemented.
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
| Name | Type | Default | Description
| ---- | ---- | ------- | -----------
| assumed_state | boolean | `False` | Return `True` if the state is based on our assumption instead of reading it from the device.
| available | boolean | `True` | Indicate if Home Assistant is able to read the state and control the underlying device.
| device_state_attributes | dict | `None` | Extra information to store in the state machine. It needs to be information that further explains the state, it should not be static information like firmware version. See [below](entity_index.md#standard_attributes) for details of standard attributes.
| entity_picture | URL | `None` | Url of a picture to show for the entity.
| name | string | `None` | Name of the entity
| should_poll | boolean | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](#methods).
| unique_id | string | `None` | A unique identifier for this entity. Needs to be unique within a platform (ie `light.hue`). Should not be configurable by the user or be changeable. [Learn more.](entity_registry_index.md#unique-id-requirements)
## Advanced properties
The following properties are also available on entities. However, they are for advanced use only and should be used with caution.
| Name | Type | Default | Description
| ---- | ---- | ------- | -----------
| force_update | boolean | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine.
| hidden | boolean | `False` | Indicate if the entity should not be shown on the frontend.
| icon | icon | `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all devices.
## Standard attributes
The following `device_state_attributes` are considered standard and should follow the convention below. The constant should be imported from `homeassistant/const.py`.
| Name | Type | Unit | Constant | Description
| ---- | ---- | ---- | -------- | -----------
| battery_charging | boolean | N/A | `ATTR_BATTERY_CHARGING` | Battery charging status of the entity, shown as a boolean `true` or `false`. If charging is not supported, then this attribute should not be created.
| battery_level | integer | % | `ATTR_BATTERY_LEVEL` | Battery level of the entity, shown as an integer percentage between 0-100.
## Lifecycle hooks
Use these lifecycle hooks to execute code when certain events happen to the entity. All lifecycle hooks are async methods.
### `async_added_to_hass()`
Called when an entity has their entity_id and hass object assigned, before it is written to the state machine for the first time. Example uses: restore the state, subscribe to updates or set callback/dispatch function/listener.
### `async_will_remove_from_hass()`
Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates.
## Changing the entity model
If you want to add a new feature to an entity or any of its subtypes (light, switch, etc), you will need to propose it first in our [architecture repo](https://github.com/home-assistant/architecture/issues). Only additions will be considered that are common features among various vendors.

View File

@ -0,0 +1,77 @@
---
title: Media Player Entity
sidebar_label: Media Player
id: version-0.93.0-entity_media_player
original_id: entity_media_player
---
> This entry is incomplete. Contribution welcome.
## Properties
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
| Name | Type | Default | Description
| ---- | ---- | ------- | -----------
| sound_mode | string | None | The current sound mode of the media player
| sound_mode_list | list | None | Dynamic list of available sound modes (set by platform, empty means sound mode not supported)
| source | string | None | The currently selected input source for the media player.
| source_list | list | None | The list of possible input sources for the media player. (This list should contain human readable names, suitible for frontend display)
| media_image_url | string | None | URL that represents the current image.
| media_image_remotely_accessible | boolean | False | Return `True` if property `media_image_url` is accessible outside of the home network.
| device_class | string | `None` | Type of binary sensor.
## Methods
### Select sound mode
Optional. Switch the sound mode of the media player.
class MyMediaPlayer(MediaPlayerDevice):
# Implement one of these methods.
def select_sound_mode(self, sound_mode):
"""Switch the sound mode of the entity."""
def async_select_sound_mode(self, sound_mode):
"""Switch the sound mode of the entity."""
### Select source
Optional. Switch the selected input source for the media player.
class MyMediaPlayer(MediaPlayerDevice):
# Implement one of these methods.
def select_source(self, source):
"""Select input source."""
def async_select_source(self, source):
"""Select input source."""
### Mediatype
Required. Returns one of the defined constants from the below list that matches the mediatype
| CONST |
|-------|
|MEDIA_TYPE_MUSIC|
|MEDIA_TYPE_TVSHOW|
|MEDIA_TYPE_MOVIE|
|MEDIA_TYPE_VIDEO|
|MEDIA_TYPE_EPISODE|
|MEDIA_TYPE_CHANNEL|
|MEDIA_TYPE_PLAYLIST|
|MEDIA_TYPE_IMAGE|
|MEDIA_TYPE_URL|
|MEDIA_TYPE_GAME|
|MEDIA_TYPE_APP|
class MyMediaPlayer(MediaPlayerDevice):
# Implement the following method.
def media_content_type(self):
"""Content type of current playing media."""
### Available device classes
Optional. What type of media device is this. It will possibly map to google device types.
| Value | Description
| ----- | -----------
| tv | Device is a television type device.
| speaker | Device is speakers or stereo type device.

View File

@ -0,0 +1,24 @@
---
title: Entity Registry
sidebar_label: Introduction
id: version-0.93.0-entity_registry_index
original_id: entity_registry_index
---
The entity registry is a registry where Home Assistant keeps track of entities. Any entity that is added to Home Assistant and has a unique ID will be registered in the registry.
Being registered has the advantage that the same entity will always get the same entity ID. It will also prevent other entities from using that entity ID.
A user is also able to override the name of an entity in the entity registry. When set, the name of the entity registry is used in favor of the name the device might give itself.
## Unique ID requirements
An entity is looked up in the registry based on a combination of the plaform type (e.g., `light`), and the integration name (domain) (ie hue) and the unique ID of the entity. It is therefore very important that the unique ID is unique! It is also important that it is not possible for the user to change the unique ID, because that means it will lose all its settings related to it.
Good sources for a unique ID:
- Serial number of a device
- MAC address of a device
- latitude/longitude
If a device has a single serial but provides multiple entities, combine the serial with unique identifiers for the entities. For example, if a device measures both temperature and humidity, you can uniquely identify the entities using `{serial}-{sensor_type}`.

View File

@ -0,0 +1,72 @@
---
title: Switch Entity
sidebar_label: Switch
id: version-0.93.0-entity_switch
original_id: entity_switch
---
## Properties
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
| Name | Type | Default | Description
| ---- | ---- | ------- | -----------
| is_on | boolean | **Required** | If the switch is currently on or off.
| current_power_w | float | `None` | The current power usage in W.
| today_energy_kwh | float | `None` | Total energy usage in kWh.
| is_standby | boolean | `None` | Indicate if the device connected to the switch is currently in standby.
## Methods
### Turn On
Turn the switch on.
```python
class MySwitch(SwitchDevice):
# Implement one of these methods.
def turn_on(self, **kwargs) -> None:
"""Turn the entity on."""
async def async_turn_on(self, **kwargs):
"""Turn the entity on."""
```
### Turn Off
Turn the switch off.
```python
class MySwitch(SwitchDevice):
# Implement one of these methods.
def turn_off(self, **kwargs):
"""Turn the entity off."""
async def async_turn_off(self, **kwargs):
"""Turn the entity off."""
```
### Toggle
Optional. If not implemented will default to checking what method to call using the `is_on` property.
```python
class MySwitch(SwitchDevice):
# Implement one of these methods.
def toggle(self, **kwargs):
"""Toggle the entity."""
async def async_toggle(self, **kwargs):
"""Toggle the entity."""
```
### Available device classes
Optional. What type of device this. It will possibly map to google device types.
| Value | Description
| ----- | -----------
| outlet | Device is an outlet for power.
| switch | Device is switch for some type of entity.

View File

@ -0,0 +1,31 @@
---
title: Developing an add-on
sidebar_label: Introduction
id: version-0.93.0-hassio_addon_index
original_id: hassio_addon_index
---
Add-ons for Hass.io allow the user to extend the functionality around Home Assistant. This can be running an application that Home Assistant can integrate with (like an MQTT broker) or to share the configuration via Samba for easy editing from other computers. Add-ons can be configured via the Hass.io panel in Home Assistant.
Under the hood, add-ons are Docker images published in [Docker Hub](https://hub.docker.com/). Developers can create [GitHub](https://github.com) repositories that contain multiple references to add-ons for easy sharing with the community.
1. [Tutorial: Making your first add-on](hassio_addon_tutorial.md)
1. [Configuration](hassio_addon_config.md)
1. [Communication](hassio_addon_communication.md)
1. [Local Testing](hassio_addon_testing.md)
1. [Publishing](hassio_addon_publishing.md)
1. [Presentation](hassio_addon_presentation.md)
1. [Repositories](hassio_addon_repository.md)
1. [Security](hassio_addon_security.md)
Useful links:
* [Hass.io Supervisor](https://github.com/home-assistant/hassio)
* [Hass.io Core Add-ons](https://github.com/home-assistant/hassio-addons)
* [Hass.io Build environment](https://github.com/home-assistant/hassio-build)
* [Hass.io base images](https://github.com/home-assistant/hassio-base)
* [Hass.io Builder](https://github.com/home-assistant/hassio-builder)
* [Hass.io community Add-ons](https://github.com/hassio-addons)
* [HassOS embedded Linux](https://github.com/home-assistant/hassos)
* [Home Assistant Dockerfile](https://github.com/home-assistant/hassio-homeassistant)

View File

@ -0,0 +1,43 @@
---
title: Add-on security
id: version-0.93.0-hassio_addon_security
original_id: hassio_addon_security
---
Hass.io rates every add-on based on the wanted rights. An add-on with a rating of 6 is very secure. If an add-on has a rating of 1, you shouldn't run this add-on unless you are 100% sure that you can trust the source.
## API Role
For access to Hass.io API you need define a role or you run in default mode. This is only required for Hass.io API not Home Assistant proxy. Any of the roles already have access to the default API calls, and do not require any additional settings.
### Available Roles
| Role | Description |
|------|-------------|
| default | Have access to all `info` calls |
| homeassistant | Can access all Home Assistant API endpoints |
| backup | Can access all snapshot API endpoints |
| manager | Is for Add-ons that run CLIs and need extended rights |
| admin | Have access to every API call. That is the only one they can disable/enable the Add-on protection mode |
## Protection
Default, all add-ons run in protection enabled mode. This mode prevents the add-on from getting any rights on the system. If an add-on requires more rights, you can disable this protection via the API add-on options for that add-on. But be careful, an add-on with disabled protection can destroy your system!
## Making a secure add-on
As a developer, follow the following best practices to make your add-on secure:
- Don't run on host network
- Create an AppArmor profile
- Map folders read only if you don't need write access
- If you need any API access, make sure that you do not grant permission that aren't needed
## Use Home Assistant User backend
Instead of allowing users to set new login credential in plain text config, use the Home Assistant [Auth backend][hassio-api-auth]. You can enable the access to API with `auth_api: true`. Now you are able to send the login credential to auth backend and validate it again Home Assistant.
We have some sample and helpers around that system collected in a [GitHub repository][hassio-auth]. Feel free to copy and paste it or provide your own scripts.
[hassio-auth]: https://github.com/home-assistant/hassio-auth
[hassio-api-auth]: https://github.com/home-assistant/hassio/blob/dev/API.md#auth--sso-api

View File

@ -0,0 +1,90 @@
---
title: Debugging Hass.io
id: version-0.93.0-hassio_debugging
original_id: hassio_debugging
---
> This section is not for end users. End users should use the [SSH add-on] to SSH into Hass.io. This is for <b>developers</b> of Hass.io. Do not ask for support if you are using these options.
[SSH add-on]: https://www.home-assistant.io/addons/ssh/
The following debug tips and tricks are for developers who are running the Hass.io image and are working on the base image. If you use the generic Linux installer script, you should be able to access your host and logs as per your host.
## Debug Supervisor
Visual Studio Code config:
```json
{
"version": "0.2.0",
"configurations": [
{
"name": "Hass.io remote debug",
"type": "python",
"request": "attach",
"port": 33333,
"host": "IP",
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
"remoteRoot": "/usr/src/hassio"
}
]
}
]
}
```
You need set the dev mode on supervisor and enable debug with options. You need also install the Remote debug Add-on from Developer Repository to expose the debug port to Host.
## SSH access to the host
### resinOS based Hass.io (deprecated)
Create an `authorized_keys` file containing your public key, and place it in the root of the boot partition of your SD card. See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. Once the device is booted, you can access your device as root over SSH on port 22222.
### HassOS based Hass.io
Use a USB drive formatted with FAT, ext4, or NTFS and name it CONFIG (case sensitive). Create an `authorized_keys` file (no extension) containing your public key, and place it in the root of the USB drive. See [Generating SSH Keys](#generating-ssh-keys) section below if you need help generating keys. From the UI, navigate to the hass.io system page and choose "Import from USB". You can now access your device as root over SSH on port 22222. Alternatively, the file will be imported from the USB when the hass.io device is rebooted.
> Make sure when you are copying the public key to the root of the USB drive that you rename the file correctly to `authorized_keys` with no `.pub` file extension.
You should then be able to SSH into your Hass.io device. On Mac/Linux, use:
```
ssh root@hassio.local -p 22222
```
You will initially be logged in to Hass.io CLI for HassOS where you can perform normal [CLI functions]. If you need access to the host system use the 'login' command. [Hass.io OS] is a hypervisor for Docker. See the [Hass.io Architecture] documentation for information regarding the Hass.io supervisor. The supervisor offers an API to manage the host and running the Docker containers. Home Assistant itself and all installed addon's run in separate Docker containers.
[CLI functions]: https://www.home-assistant.io/hassio/commandline/
[Hass.io OS]: https://github.com/home-assistant/hassos
[Hass.io Architecture]: https://developers.home-assistant.io/docs/en/architecture_hassio.html
## Checking the logs
```bash
# Logs from the supervisor service on the Host OS
journalctl -f -u hassos-supervisor.service
# Hass.io supervisor logs
docker logs hassos_supervisor
# Home Assistant logs
docker logs homeassistant
```
## Accessing the container bash
```bash
docker exec -it homeassistant /bin/bash
```
[windows-keys]: https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-putty-on-digitalocean-droplets-windows-users
### Generating SSH Keys
Windows instructions for how to generate and use private/public keys with Putty are [here][windows-keys]. Instead of the droplet instructions, add the public key as per above instructions.
Alternative instructions, for Mac, Windows and Linux can be found [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#platform-mac).
Follow steps 1-4 under 'Generating a new SSH key' (The other sections are not applicable to Hass.io and can be ignored.)
Step 3 in the link above, shows the path to the private key file `id_rsa` for your chosen operating system. Your public key, `id_rsa.pub`, is saved in the same folder. Next, select all text from text box "Public key for pasting into the authorized_keys file" and save it to the root of your USB drive as `authorized_keys`.

View File

@ -1,4 +1,5 @@
[
"0.93.0",
"0.92.1",
"0.92.0",
"0.91.2",