mirror of
https://github.com/home-assistant/developers.home-assistant.git
synced 2025-07-16 22:06:29 +00:00
Version 0.72
This commit is contained in:
parent
f386ddf7f9
commit
13d8709e60
93
website/pages/en/versions.js
Normal file
93
website/pages/en/versions.js
Normal file
@ -0,0 +1,93 @@
|
||||
/**
|
||||
* Copyright (c) 2017-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
const React = require('react');
|
||||
|
||||
const CompLibrary = require('../../core/CompLibrary');
|
||||
const Container = CompLibrary.Container;
|
||||
const GridBlock = CompLibrary.GridBlock;
|
||||
|
||||
const CWD = process.cwd();
|
||||
|
||||
const siteConfig = require(CWD + '/siteConfig.js');
|
||||
const versions = require(CWD + '/versions.json');
|
||||
|
||||
class Versions extends React.Component {
|
||||
render() {
|
||||
const latestVersion = versions[0];
|
||||
return (
|
||||
<div className="docMainWrapper wrapper">
|
||||
<Container className="mainContainer versionsContainer">
|
||||
<div className="post">
|
||||
<header className="postHeader">
|
||||
<h2>{siteConfig.title + ' Versions'}</h2>
|
||||
</header>
|
||||
<p>New versions of this project are released every so often.</p>
|
||||
<h3 id="latest">Current version (Stable)</h3>
|
||||
<table className="versions">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>{latestVersion}</th>
|
||||
<td>
|
||||
<a href={''}>Documentation</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href={''}>Release Notes</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
This is the version that is configured automatically when you
|
||||
first install this project.
|
||||
</p>
|
||||
<h3 id="rc">Pre-release versions</h3>
|
||||
<table className="versions">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>master</th>
|
||||
<td>
|
||||
<a href={''}>Documentation</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href={''}>Release Notes</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<p>Other text describing this section.</p>
|
||||
<h3 id="archive">Past Versions</h3>
|
||||
<table className="versions">
|
||||
<tbody>
|
||||
{versions.map(
|
||||
version =>
|
||||
version !== latestVersion && (
|
||||
<tr>
|
||||
<th>{version}</th>
|
||||
<td>
|
||||
<a href={''}>Documentation</a>
|
||||
</td>
|
||||
<td>
|
||||
<a href={''}>Release Notes</a>
|
||||
</td>
|
||||
</tr>
|
||||
)
|
||||
)}
|
||||
</tbody>
|
||||
</table>
|
||||
<p>
|
||||
You can find past versions of this project{' '}
|
||||
<a href="https://github.com/"> on GitHub </a>.
|
||||
</p>
|
||||
</div>
|
||||
</Container>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Versions;
|
@ -0,0 +1,55 @@
|
||||
---
|
||||
title: Components Architecture
|
||||
sidebar_label: Components
|
||||
id: version-0.72-architecture_components
|
||||
original_id: architecture_components
|
||||
---
|
||||
|
||||
Home Assistant can be extended with **components**. Each component is responsible for a specific domain within Home Assistant. Components can listen for or trigger events, offer services, and maintain states. Components are written in Python and can do all the goodness that Python has to offer. Out of the box, Home Assistant offers a bunch of [built-in components](https://www.home-assistant.io/components/).
|
||||
|
||||
<img src='/img/en/architecture/component_interaction.png' alt='Diagram showing interaction between components and the Home Assistant core.'>
|
||||
|
||||
There are two types of components within Home Assistant: components that interact with an Internet of Things domain, and components that respond to events that happen within Home Assistant. Read on to learn about each type!
|
||||
|
||||
## Components that interact with an Internet-of-Things domain
|
||||
|
||||
These components track devices within a specific domain and consist of a core part and platform-specific logic. These components make their information available via the State Machine and the Event Bus. The components also register services in the Service Registry to expose control of the devices.
|
||||
|
||||
For example, the built-in [`switch` component](https://www.home-assistant.io/components/switch/) is responsible for interaction with different types of switches. A platform provides support for a particular kind or brand of device. For example, a switch could use a WeMo or Orvibo platform and a light component might interact with the Hue or LIFX platform.
|
||||
|
||||
If you want to add support for a new platform, check out the [add new platform section](creating_platform_index.md).
|
||||
|
||||
## Components that respond to events that happen within Home Assistant
|
||||
|
||||
These components provide small pieces of home automation logic or involve services that do common tasks within your house.
|
||||
|
||||
For example, the [`device_sun_light_trigger` component](https://www.home-assistant.io/components/device_sun_light_trigger/) tracks the state of devices and the sun to make sure that the lights are turned on when it gets dark and people are home. The component uses logic like this:
|
||||
|
||||
```text
|
||||
In the event that device 'Paulus Nexus 5' changes to the 'Home' state:
|
||||
If the sun has set and the lights are not on:
|
||||
Turn on the lights
|
||||
```
|
||||
|
||||
```text
|
||||
In the event that the combined state of all tracked devices changes to 'Not Home':
|
||||
If the lights are on:
|
||||
Turn off the lights
|
||||
```
|
||||
|
||||
```text
|
||||
In the event of the sun setting:
|
||||
If the lights are off and the combined state of all tracked device equals 'Home':
|
||||
Turn on the lights
|
||||
```
|
||||
|
||||
## The full picture
|
||||
|
||||
When we put all the different pieces of Home Assistant together, it's a close match for the initial home automation overview sketch. The smart home AI has not been implemented yet, so it's not included in this picture.
|
||||
|
||||
<img
|
||||
src='/img/en/architecture/ha_full_architecture.png'
|
||||
alt='Overview of the full Home Assistant architecture with a couple of loaded components and platforms'
|
||||
/>
|
||||
|
||||
The platform logic for components uses third-party Python libraries to communicate with the devices. Through this, we can leverage some of the best libraries in the Python community.
|
43
website/versioned_docs/version-0.72/architecture_entities.md
Normal file
43
website/versioned_docs/version-0.72/architecture_entities.md
Normal file
@ -0,0 +1,43 @@
|
||||
---
|
||||
title: Entity Architecture
|
||||
sidebar_label: Entity
|
||||
id: version-0.72-architecture_entities
|
||||
original_id: architecture_entities
|
||||
---
|
||||
|
||||

|
||||
|
||||
## Configuration
|
||||
|
||||
Configuration is provided by the [configuration.yaml file](configuration_yaml_index.md) or by a [Config Entry](config_entries_index.md).
|
||||
|
||||
## Component
|
||||
|
||||
Examples of components: `light`, `switch`.
|
||||
|
||||
The component is responsible for defining the Abstract Entity Class and services to control the entities.
|
||||
|
||||
## Entity Component
|
||||
|
||||
The Entity Component is responsible for:
|
||||
|
||||
- Distributing the configuration to the platforms
|
||||
- Forward config entries and discoveries
|
||||
- Collect entities for service calls
|
||||
- Optionally maintain a group of all entities
|
||||
|
||||
## Entity Platform
|
||||
|
||||
The Entity Platform manages all entities for the platform and polls them for updates if necessary.
|
||||
|
||||
When adding entities, the Entity Platform will query the Entity Registry to make sure that the entities to be added have the correct entity IDs.
|
||||
|
||||
## Entity Registry
|
||||
|
||||
The [Entity Registry](entity_registry_index.md) will track entities and allows users to store extra settings for an entity.
|
||||
|
||||
## Platform
|
||||
|
||||
Examples of platforms: `light.hue`, `switch.wemo`.
|
||||
|
||||
Platform uses configuration to query the external device/service and add entities to the entity platform.
|
31
website/versioned_docs/version-0.72/architecture_hassio.md
Normal file
31
website/versioned_docs/version-0.72/architecture_hassio.md
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: Hass.io Architecture
|
||||
sidebar_label: Hass.io
|
||||
id: version-0.72-architecture_hassio
|
||||
original_id: architecture_hassio
|
||||
---
|
||||
|
||||

|
||||
|
||||
## Host Control (HC)
|
||||
|
||||
This is a daemon running on the host machine that allows the supervisor to control certain aspects of the host OS:
|
||||
|
||||
- Power cycle (restart, turn off)
|
||||
- Manage network settings
|
||||
- Local updates
|
||||
|
||||
## Host
|
||||
|
||||
Our pre-build images are based on [ResinOS]. Any Linux machine can be turned into a Hass.io host by running [the installer][linux].
|
||||
|
||||
## Supervisor
|
||||
|
||||
The supervisor offers an API to manage the host and running the Docker containers.
|
||||
|
||||
## Configuration panel
|
||||
|
||||
The configuration panel lives inside the supervisor but is accessible via the Home Assistant user interface. The configuration panel allows the user to manage the installation.
|
||||
|
||||
[ResinOS]: https://resinos.io/
|
||||
[linux]: https://www.home-assistant.io/hassio/installation/#alternative-install-on-generic-linux-server
|
31
website/versioned_docs/version-0.72/architecture_index.md
Normal file
31
website/versioned_docs/version-0.72/architecture_index.md
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: Architecture
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-architecture_index
|
||||
original_id: architecture_index
|
||||
---
|
||||
|
||||
Before we dive into the Home Assistant architecture, let's get a clear overview of the home automation landscape as a whole. This way, we can show how the different parts of Home Assistant fit into the picture.
|
||||
|
||||
For more information about each part in this overview, <a href='https://www.home-assistant.io/blog/2014/12/26/home-control-home-automation-and-the-smart-home/'>check out our blog</a>. Here's the tl;dr version of the blog:
|
||||
|
||||
* Home Control is responsible for collecting information and controlling devices.
|
||||
* Home Automation triggers commands based on user configurations.
|
||||
* Smart Home triggers commands based on previous behavior.
|
||||
|
||||
<img
|
||||
src='/img/en/architecture/home_automation_landscape.svg'
|
||||
alt='Home Automation landscape'
|
||||
/>
|
||||
|
||||
The Home Assistant core is responsible for Home Control. Home Assistant contains four parts which make this possible:
|
||||
|
||||
* **Event Bus**: facilitates the firing and listening of events -- the beating heart of Home Assistant.
|
||||
* **State Machine**: keeps track of the states of things and fires a `state_changed` event when a state has been changed.
|
||||
* **Service Registry**: listens on the event bus for `call_service` events and allows other code to register services.
|
||||
* **Timer**: sends a `time_changed` event every 1 second on the event bus.
|
||||
|
||||
<img
|
||||
alt='Overview of the Home Assistant core architecture'
|
||||
src='/img/en/architecture/ha_architecture.svg'
|
||||
/>
|
13
website/versioned_docs/version-0.72/asyncio_101.md
Normal file
13
website/versioned_docs/version-0.72/asyncio_101.md
Normal file
@ -0,0 +1,13 @@
|
||||
---
|
||||
title: Asyncio 101
|
||||
id: version-0.72-asyncio_101
|
||||
original_id: asyncio_101
|
||||
---
|
||||
|
||||
If you are not familiar yet with asyncio, please watch the below video. It's a great introduction by [Robert Smallshire][rob] in how and why asyncio works the way it does.
|
||||
|
||||
<div class='videoWrapper'>
|
||||
<iframe width="560" height="315" src="https://www.youtube.com/embed/M-UcUs7IMIM" frameborder="0" allowfullscreen></iframe>
|
||||
</div>
|
||||
|
||||
[rob]: https://github.com/rob-smallshire
|
@ -0,0 +1,69 @@
|
||||
---
|
||||
title: Categorizing Functions
|
||||
id: version-0.72-asyncio_categorizing_functions
|
||||
original_id: asyncio_categorizing_functions
|
||||
---
|
||||
|
||||
A piece of work within Home Assistant is represented by a function that will be invoked. It will either run inside our event loop or inside our thread pool, depending on if it is async safe.
|
||||
|
||||
Home Assistant uses the convention that all functions that must be run from within the event loop are prefixed with `async_`.
|
||||
|
||||
## The coroutine function
|
||||
|
||||
Coroutines are special functions based on Python’s generators syntax which allows them to suspend execution while waiting on a result.
|
||||
|
||||
Invoking a coroutine function will return a Generator object back, but will not actually begin execution. This object will execute the task when it is either yielded from (from within another coroutine) or it is scheduled on the event loop.
|
||||
|
||||
To declare a function a coroutine, import the coroutine annotation from the asyncio package and annotate your function.
|
||||
|
||||
```python
|
||||
async def async_look_my_coroutine(target):
|
||||
result = await entity.async_turn_on()
|
||||
if result:
|
||||
print("hello {}".format(target))
|
||||
|
||||
hass.loop.create_task(async_look_my_coroutine("world"))
|
||||
```
|
||||
|
||||
In this example, we schedule the coroutine by calling `hass.loop.create_task`. This will add the coroutine to the queue of tasks to be run. When the event loop is running `async_look_my_coroutine` it will suspend the task when `yield from entity.async_turn_on()` is called. At that point a new task will be scheduled to execute `entity.async_turn_on()`. When that job has been executed, `async_look_my_coroutine` will resume.
|
||||
|
||||
## The callback function
|
||||
|
||||
This is a normal function that is considered safe to be run from within the event loop. A callback is unable to suspend itself and thus cannot do any I/O or call a coroutine. A callback is capable of scheduling a new task but it will not be able to wait for the results.
|
||||
|
||||
To declare a function as a callback, import the callback annotation from the core package and annotate your function.
|
||||
|
||||
A common use case for a callback in Home Assistant is as a listener for an event or a service call. It can process the incoming information and then schedule the right calls to be made. Example from the automation component.
|
||||
|
||||
```python
|
||||
from homeassistant.core import callback
|
||||
|
||||
@callback
|
||||
def async_trigger_service_handler(service_call):
|
||||
"""Handle automation trigger service calls."""
|
||||
vars = service_call.data.get(ATTR_VARIABLES)
|
||||
for entity in component.async_extract_from_service(service_call):
|
||||
hass.loop.create_task(entity.async_trigger(vars, True))
|
||||
```
|
||||
|
||||
In this example, `entity.async_trigger` is a coroutine function. Invoking the coroutine function will return a coroutine task. The passed in parameters will be used when the task gets executed.
|
||||
|
||||
To execute the task we have to schedule it for execution on the event loop. This is done by calling `hass.loop.create_task`.
|
||||
|
||||
### Why even have callbacks?
|
||||
|
||||
You might wonder, if a coroutine can do everything a callback can do, why even have a callback. The reason is performance and better state consistency of the core API objects.
|
||||
|
||||
When coroutine A waits for coroutine B, it will suspend itself and schedule a new task to run B. This means that the event loop is now running A, B and then A again. If B is a callback, A will never have to suspend itself and thus the event loop is just running A. The consistency implication is that other events queued to run on the event loop continue to wait until callbacks complete, but will be interleaved when yielding to another coroutine.
|
||||
|
||||
## Event loop and thread safe
|
||||
|
||||
These are functions that are safe to run both in a thread and inside the event loop. These functions are usually performing a computation or transform data in memory. Anything that does I/O does not fall under this category. Many standard library functions fall in this category. For example generating the sum of a set of numbers using sum or merging two dictionaries.
|
||||
|
||||
There is no special annotation to mark functions as part of this category and care should be taken when using these functions from inside the event loop. When in doubt, look at their implementation.
|
||||
|
||||
## Other functions
|
||||
|
||||
These are all the functions that did not fit in the previous categories. These functions are either thread-safe or not considered safe to be run within the event loop. These are functions that use sleep, or perform I/O.
|
||||
|
||||
There is no special annotation necessary to be considered part of this category.
|
21
website/versioned_docs/version-0.72/asyncio_index.md
Normal file
21
website/versioned_docs/version-0.72/asyncio_index.md
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
title: Asynchronous Programming
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-asyncio_index
|
||||
original_id: asyncio_index
|
||||
---
|
||||
|
||||
On September 29, 2016 we released [Home Assistant 0.29][0.29] as part of our bi-weekly release schedule. This release introduced a complete overhaul of the core spearheaded by [Ben Bangert][ben].
|
||||
|
||||
The old core was set up like a “traditional” threaded application. Each resource that was not thread safe (ie. the state of entities) would be protected by a lock. This caused a lot of waiting and potential inconsistency because a task could now end up waiting halfway through its job until some resource got freed.
|
||||
|
||||
Our new core is based on an Python’s built-in asyncio module. Instead of having all threads have access to the core API objects, access is now limited to a special thread called the event loop. All components will now schedule themselves as a task to be executed by the event loop. This gives us the guarantee that only one task is executed at once, meaning we no longer need any locks.
|
||||
|
||||
The only problem with running everything inside the event loop is when a task is doing blocking I/O, what most third-party Python libraries are doing. For example while requesting new information from a device, the core will stop running until we get a response from the device. To handle this, a task is able to suspend itself until the response is available after which it will be enqueued for the event loop to process the result.
|
||||
|
||||
For a task to be able to suspend itself, all code that it calls has to have this capability added. This means in practice that each device integration will need a full rewrite of the library that offers the integration! As this is not something that can be achieved, ever, a 100% backwards compatible API has been added so that no platform will require updating.
|
||||
|
||||
The backwards compatible API works by scheduling a task from a different thread and blocking that thread until the task has been processed by the event loop.
|
||||
|
||||
[0.29]: https://www.home-assistant.io/blog/2016/09/29/async-sleepiq-emoncms-stocks/
|
||||
[ben]: https://github.com/bbangert/
|
@ -0,0 +1,112 @@
|
||||
---
|
||||
title: Working with Async
|
||||
id: version-0.72-asyncio_working_with_async
|
||||
original_id: asyncio_working_with_async
|
||||
---
|
||||
|
||||
Although we have a backwards compatible API, using the async core directly will be a lot faster. Most core components have already been rewritten to leverage the async core. This includes the EntityComponent helper (foundation of light, switch, etc), scripts, groups and automation.
|
||||
|
||||
## Interacting with the core
|
||||
|
||||
[All methods in the Home Assistant core][dev-docs] are implemented in two flavors: an async version and a version to be called from other threads. The versions for other are merely wrappers that call the async version in a threadsafe manner using [the available async utilities][dev-docs-async].
|
||||
|
||||
So if you are making calls to the core (the hass object) from within a callback or coroutine, use the methods that start with async_. If you need to call an async_ function that is a coroutine, your task must also be a coroutine.
|
||||
|
||||
## Implementing an async component
|
||||
|
||||
To make a component async, implement an async_setup.
|
||||
|
||||
```python
|
||||
def setup(hass, config):
|
||||
# Setup your component outside of the event loop.
|
||||
```
|
||||
|
||||
Will turn into:
|
||||
|
||||
```python
|
||||
async def async_setup(hass, config):
|
||||
# Setup your component inside of the event loop.
|
||||
```
|
||||
|
||||
## Implementing an async platform
|
||||
|
||||
For platforms we support async setup. Instead of setup_platform you need to have a coroutine async_setup_platform.
|
||||
|
||||
```python
|
||||
setup_platform(hass, config, add_entities, discovery_info=None):
|
||||
# Setup your platform outside of the event loop.
|
||||
```
|
||||
|
||||
Will turn into:
|
||||
|
||||
```python
|
||||
async def async_setup_platform(hass, config, async_add_entities,
|
||||
discovery_info=None):
|
||||
# Setup your platform inside of the event loop
|
||||
```
|
||||
|
||||
The only difference with the original parameters is that the `add_entities` function has been replaced by the async friendly callback `async_add_entities`.
|
||||
|
||||
## Implementing an async entity
|
||||
|
||||
You can make your entity async friendly by converting your update method to be async. This requires the dependency of your entities to also be async friendly!
|
||||
|
||||
```python
|
||||
class MyEntity(Entity):
|
||||
def update(self):
|
||||
"""Retrieve latest state."""
|
||||
self._state = fetch_state()
|
||||
```
|
||||
|
||||
Will turn into:
|
||||
|
||||
```python
|
||||
class MyEntity(Entity):
|
||||
async def async_update(self):
|
||||
"""Retrieve latest state."""
|
||||
self._state = await async_fetch_state()
|
||||
```
|
||||
|
||||
Make sure that all properties defined on your entity do not result in I/O being done. All data has to be fetched inside the update method and cached on the entity. This is because these properties are read from within the event loop and thus doing I/O will result in the core of Home Assistant waiting until your I/O is done.
|
||||
|
||||
## Calling async functions from threads
|
||||
|
||||
Sometimes it will happen that you’re in a thread and you want to call a function that is only available as async. Home Assistant includes a few async helper utilities to help with this.
|
||||
|
||||
In the following example, `say_hello` will schedule `async_say_hello` and block till the function has run and get the result back.
|
||||
|
||||
```python
|
||||
from homeassistant.util.async import run_callback_threadsafe
|
||||
|
||||
def say_hello(hass, target):
|
||||
return run_callback_threadsafe(
|
||||
hass.loop, async_say_hello, target).result()
|
||||
|
||||
def async_say_hello(hass, target):
|
||||
return "Hello {}!".format(target)
|
||||
```
|
||||
|
||||
## Dealing with passed in functions
|
||||
|
||||
If your code takes in functions from other code, you will not know which category the function belongs to and how they should be invoked. This usually only occurs if your code supplies an event helper like `mqtt.async_subscribe` or `track_state_change_listener`.
|
||||
|
||||
To help with this, there are two helper methods on the hass object that you can call from inside the event loop:
|
||||
|
||||
#### hass.async_run_job
|
||||
|
||||
Use this method if the function should be called as soon as possible. This will call callbacks immediately, schedule coroutines for execution on the event loop and schedule other functions to be run inside the thread pool.
|
||||
|
||||
| Callback | Call immediately.
|
||||
| Coroutine | Schedule for execution on the event loop.
|
||||
| Other functions | Schedule for execution in the thread pool.
|
||||
|
||||
#### hass.async_add_job
|
||||
|
||||
Use this method if the function should be called but not get priority over already scheduled calls.
|
||||
|
||||
| Callback | Schedule for execution on the event loop.
|
||||
| Coroutine | Schedule for execution on the event loop.
|
||||
| Other functions | Schedule for execution in the thread pool.
|
||||
|
||||
[dev-docs]: https://dev-docs.home-assistant.io/en/master/api/core.html
|
||||
[dev-docs-async]: https://dev-docs.home-assistant.io/en/dev/api/util.html#module-homeassistant.util.async
|
90
website/versioned_docs/version-0.72/auth_api.md
Normal file
90
website/versioned_docs/version-0.72/auth_api.md
Normal file
@ -0,0 +1,90 @@
|
||||
---
|
||||
title: Authentication API
|
||||
sidebar_label: API
|
||||
id: version-0.72-auth_api
|
||||
original_id: auth_api
|
||||
---
|
||||
|
||||
> This is experimental. It is not persisted and is not yet intended for production.
|
||||
|
||||
This page will describe the steps required to fetch an access token for a user and how to refresh it. We follow the OAuth 2 specification.
|
||||
|
||||
## Requirements
|
||||
|
||||
A client needs to be created inside Home Assistant before a client can request users to authorize it or fetch a new access token. The only way currently to create a client is programmatically:
|
||||
|
||||
```python
|
||||
client = await hass.auth.async_create_client(
|
||||
'Example client',
|
||||
redirect_uris=['http://www.example.com/hass_callback'],
|
||||
no_secret=True,
|
||||
)
|
||||
print(client.id)
|
||||
```
|
||||
|
||||
## Authorize
|
||||
|
||||
[](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd)
|
||||
|
||||
- The authorize url should contain `client_id`, `redirect_uri` and, if available, `client_secret` as query parameters. Example: `http://your-instance.com/auth/authorize?client_id=ABCDE&client_secret=QWERTY&redirect_uri=https%3A%2F%2Fexample.com%2Fhass_callback`
|
||||
- The user will navigate to this link, log into Home Assistant and authorize the client.
|
||||
- Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code as part of the query parameters. Example: https://example.com/hass_callback?code=12345
|
||||
- This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section).
|
||||
- As specified in the OAuth 2 specification, it is possible to pass an optional state string to the authorize url using the `state` query parameter. This string will be added as query parameter to the redirect url.
|
||||
|
||||
## Token
|
||||
|
||||
The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token.
|
||||
|
||||
All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`.
|
||||
|
||||
### Authorization code
|
||||
|
||||
Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is:
|
||||
|
||||
```
|
||||
grant_type=authorization_code&code=12345
|
||||
```
|
||||
|
||||
The return response will be an access and refresh token:
|
||||
|
||||
```json
|
||||
{
|
||||
"access_token": "ABCDEFGH",
|
||||
"expires_in": 1800,
|
||||
"refresh_token": "IJKLMNOPQRST",
|
||||
"token_type": "Bearer"
|
||||
}
|
||||
```
|
||||
|
||||
### Refresh token
|
||||
|
||||
Use the grant type `refresh_token` to retrieve an access token using a refresh token. The request body is:
|
||||
|
||||
```
|
||||
grant_type=refresh_token&refresh_token=QWERTY
|
||||
```
|
||||
|
||||
The return response will be an access token:
|
||||
|
||||
```json
|
||||
{
|
||||
"access_token": "ABCDEFGH",
|
||||
"expires_in": 1800,
|
||||
"token_type": "Bearer"
|
||||
}
|
||||
```
|
||||
|
||||
## Making authenticated requests
|
||||
|
||||
Once you have an access token, you can make authenticated requests to the Home Assistant APIs.
|
||||
|
||||
For the websocket connection, pass the access token in the [authentication message](http://localhost:3000/docs/en/external_api_websocket.html#authentication-phase).
|
||||
|
||||
For HTTP requests, pass the token type and access token as the authorization header:
|
||||
|
||||
```
|
||||
Authorization: Bearer ABCDEFGH
|
||||
```
|
||||
|
||||
If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and the client should ask the user to authorize again.
|
26
website/versioned_docs/version-0.72/auth_auth_provider.md
Normal file
26
website/versioned_docs/version-0.72/auth_auth_provider.md
Normal file
@ -0,0 +1,26 @@
|
||||
---
|
||||
title: Authentication Providers
|
||||
id: version-0.72-auth_auth_provider
|
||||
original_id: auth_auth_provider
|
||||
---
|
||||
|
||||
Authentication providers confirm the identity of users. The user proofs their identity by going through the login flow for an auth provider. The auth provider defines the login flow and can ask the user all information this needs. This will commonly be username and password but could also include a 2FA token or other challenges.
|
||||
|
||||
Once an authentication provider has confirmed the identity of a user, it will pass that on to Home Assistant in the form of a Credentials object.
|
||||
|
||||
## Defining an auth provider
|
||||
|
||||
> We currently only support built-in auth providers. Support for custom auth providers might arrive in the future.
|
||||
|
||||
Auth providers are defined in `homeassistant/auth_providers/<name of provider>.py`. The auth provider module will need to provide an implementation of the `AuthProvider` class and contain a credential flow. This flow is what asks user for information and validates it.
|
||||
|
||||
For an example of a fully implemented auth provider, please see [insecure_example.py](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/auth_providers/insecure_example.py).
|
||||
|
||||
Auth providers can extend the following methods.
|
||||
|
||||
| method | Required | Description
|
||||
| ------ | -------- | -----------
|
||||
| async def async_credential_flow(self) | Yes | Return an instance of the credential flow for a user to identify itself.
|
||||
| async def async_get_or_create_credentials(self, flow_result) | Yes | Given the result of a credential flow, return a credentials object. This can either be an existing one or a new one.
|
||||
| async def async_initialize(self) | No | Callback callled once before interacting with the auth provider for the first time.
|
||||
| async def async_user_meta_for_credentials(credentials) | No | Callback called Home Assistant is going to create a user from a Credentials object. Can be used to populate extra fields for the user.
|
42
website/versioned_docs/version-0.72/auth_index.md
Normal file
42
website/versioned_docs/version-0.72/auth_index.md
Normal file
@ -0,0 +1,42 @@
|
||||
---
|
||||
title: Authentication
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-auth_index
|
||||
original_id: auth_index
|
||||
---
|
||||
|
||||
> This is an experimental and unfinished API introduced in Home Assistant 0.69 and later. This is not enabled by default, it's not persisted to disk and should not be used in production.
|
||||
|
||||
Home Assistant has a built-in authentication system allowing different users to interact with Home Assistant. The authentication system consist of various parts.
|
||||
|
||||

|
||||
|
||||
## Authentication providers
|
||||
|
||||
An authentication provider is used for users to authenticate themselves. It's up to the authentication provider to choose the method of authentication and the backend to use. By default we enable the built-in Home Assistant authentication provider which stores the users securely inside your configuration directory.
|
||||
|
||||
The authentication providers that Home Assistant will use are specified inside `configuration.yaml`. It is possible to have multiple instances of the same authentication provider active. In that case, each will be identified by a unique identifier. Authentication providers of the same type will not share credentials.
|
||||
|
||||
## Credentials
|
||||
|
||||
Credentials store the authentication of a user with a specific authentication provider. It is produced when a user successfully authenticates. It will allow the system to find the user in our system. If the user does not exist, a new user will be created. This user will not be activated but will require approval by the owner.
|
||||
|
||||
It is possible for a user to have multiple credentials linked to it. However, it can only have a single credential per specific authentication provider.
|
||||
|
||||
## Users
|
||||
|
||||
Each person is a user in the system. To log in as a specific user, authenticate with any of the authentication providers that are linked to this user. When a user logs in, it will get a refresh and an access token to make requests to Home Assistant.
|
||||
|
||||
### Owner
|
||||
|
||||
The first user to log in to Home Assistant will be marked as the owner. This user is able to manage users.
|
||||
|
||||
## Clients
|
||||
|
||||
Clients are applications that users use to access the Home Assistant API. Each client has a client identifier, a redirect uri and an optional client secret. The redirect uri is used to redirect the user after it has successfully authorized.
|
||||
|
||||
## Access and refresh tokens
|
||||
|
||||
The client will be provided with an authorization code when a user successfully authorizes with Home Assistant. This code can be used to retrieve an access and a refresh token. The access token will have a limited lifetime while refresh tokens will remain valid until a user deletes it.
|
||||
|
||||
The access token is used to access the Home Assistant APIs. The refresh token is used to retrieve a new valid access token.
|
@ -0,0 +1,80 @@
|
||||
---
|
||||
title: Config Flow Handlers
|
||||
id: version-0.72-config_entries_config_flow_handler
|
||||
original_id: config_entries_config_flow_handler
|
||||
---
|
||||
|
||||
Config Entries uses the [Data Flow Entry framework](data_entry_flow_index.md) to allow users to create entries. Components that want to support config entries will need to define a Config Flow Handler. This handler will manage the creation of entries from user input, discovery or other sources (like hassio).
|
||||
|
||||
Config Flow Handlers controll the data that is stored in a config entry. This means that there is no need to validate that the config is correct when Home Assistant starts up. It will also prevent breaking changes, because we will be able to migrate configuration entries to new formats if the version changes.
|
||||
|
||||
When instantiating the handler, Home Assistant will make sure to load all dependencies and install the requirements of the component.
|
||||
|
||||
To register your config flow handler with Home Assistant, register it with the config entries `HANDLERS` registry:
|
||||
|
||||
```python
|
||||
from homeassistant import config_entries, data_entry_flow
|
||||
|
||||
@config_entries.HANDLERS.register(DOMAIN)
|
||||
class ExampleConfigFlow(data_entry_flow.FlowHandler):
|
||||
```
|
||||
|
||||
> Temporarily, all config flow handlers will also need to add their component name to the `FLOWS` constant in `homeassistant/config_entries.py`. We are working on automating discovery.
|
||||
|
||||
## Initializing a config flow from an external source
|
||||
|
||||
You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing the config entry:
|
||||
|
||||
```python
|
||||
await hass.config_entries.flow.async_init(
|
||||
'hue', source=data_entry_flow.SOURCE_DISCOVERY, data=discovery_info)
|
||||
```
|
||||
|
||||
The config flow handler will need to add a step to support the given source. The step should follow the same return values as a normal step.
|
||||
|
||||
```python
|
||||
@config_entries.HANDLERS.register(DOMAIN)
|
||||
class ExampleConfigFlow(data_entry_flow.FlowHandler):
|
||||
|
||||
async def async_step_discovery(self, info):
|
||||
# Handle discovery info
|
||||
```
|
||||
|
||||
If the result of the step is to show a form, the user will be able to continue
|
||||
the flow from the config panel.
|
||||
|
||||
## Translations
|
||||
|
||||
Translations for the config flow handlers are defined under the `config` key in the component translation file `strings.json`. Example of the Hue component:
|
||||
|
||||
```json
|
||||
{
|
||||
"config": {
|
||||
"title": "Philips Hue Bridge",
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "Pick Hue bridge",
|
||||
"data": {
|
||||
"host": "Host"
|
||||
}
|
||||
},
|
||||
"link": {
|
||||
"title": "Link Hub",
|
||||
"description": "Press the button on the bridge to register Philips Hue with Home Assistant.\n\n"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"register_failed": "Failed to register, please try again",
|
||||
"linking": "Unknown linking error occurred."
|
||||
},
|
||||
"abort": {
|
||||
"discover_timeout": "Unable to discover Hue bridges",
|
||||
"no_bridges": "No Philips Hue bridges discovered",
|
||||
"all_configured": "All Philips Hue bridges are already configured",
|
||||
"unknown": "Unknown error occurred",
|
||||
"cannot_connect": "Unable to connect to the bridge",
|
||||
"already_configured": "Bridge is already configured"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
39
website/versioned_docs/version-0.72/config_entries_index.md
Normal file
39
website/versioned_docs/version-0.72/config_entries_index.md
Normal file
@ -0,0 +1,39 @@
|
||||
---
|
||||
title: Config Entries
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-config_entries_index
|
||||
original_id: config_entries_index
|
||||
---
|
||||
|
||||
Config Entries are configuration data that are persistently stored by Home Assistant. A config entry is created by a user via the UI. The UI flow is powered by a [config flow handler](config_entries_config_flow_handler.md) as defined by the component.
|
||||
|
||||
## Setting up an entry
|
||||
|
||||
During startup, Home Assistant first call the [normal component setup](https://developers.home-assistant.io/docs/en/creating_component_index.html),
|
||||
and then call the method `async_setup_entry(hass, entry)` for each entry. If a new Config Entry is
|
||||
created at runtime, Home Assistant will also call `async_setup_entry(hass, entry)` ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L119)).
|
||||
|
||||
#### For platforms
|
||||
|
||||
If a component includes platforms, it will need to forward the Config Entry to the platform. This can
|
||||
be done by calling the forward function on the config entry manager ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/bridge.py#L81)):
|
||||
|
||||
```python
|
||||
# Use `hass.async_add_job` to avoid a circular dependency between the platform and the component
|
||||
hass.async_add_job(hass.config_entries.async_forward_entry_setup(config_entry, 'light'))
|
||||
```
|
||||
|
||||
For a platform to support config entries, it will need to add a setup entry method ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/light/hue.py#L60)):
|
||||
|
||||
```python
|
||||
async def async_setup_entry(hass, config_entry, async_add_devices):
|
||||
```
|
||||
|
||||
## Unloading entries
|
||||
|
||||
Components can optionally support unloading a config entry. When unloading an entry, the component needs
|
||||
to clean up all entities, unsubscribe any event listener and close all connections. To implement this,
|
||||
add `async_unload_entry(hass, entry)` to your component ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/hue/__init__.py#L136)).
|
||||
|
||||
Platforms will not need to add any logic for unloading a config entry. The entity component will take care of this.
|
||||
If you need to clean up resources used for an entity, implement the `async_will_remove_from_hass` method on the Entity ([example](https://github.com/home-assistant/home-assistant/blob/0.68.0/homeassistant/components/media_player/cast.py#L313)).
|
@ -0,0 +1,58 @@
|
||||
---
|
||||
title: Configuration.yaml
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-configuration_yaml_index
|
||||
original_id: configuration_yaml_index
|
||||
---
|
||||
|
||||
`configuration.yaml` is a configuration file defined by the user. It is automatically created by Home Assistant on first launch. It defines which components to load.
|
||||
|
||||
## Pre-processing
|
||||
|
||||
Home Assistant will do some pre-processing on the config based on the components that are specified to load.
|
||||
|
||||
### CONFIG_SCHEMA
|
||||
|
||||
If a component defines a variable `CONFIG_SCHEMA`, the config object that is passed in will be the result of running the config through `CONFIG_SCHEMA`. `CONFIG_SCHEMA` should be a voluptuous schema.
|
||||
|
||||
### PLATFORM_SCHEMA
|
||||
|
||||
If a component defines a variable `PLATFORM_SCHEMA`, the component will be treated as an entity component. The configuration of entity components is a list of platform configurations.
|
||||
|
||||
Home Assistant will gather all platform configurations for this component. It will do so by looking for configuration entries under the domain of the component (ie `light`) but also under any entry of domain + extra text.
|
||||
|
||||
While gathering the platform configs, Home Assistant will validate them. It will see if the platform exists and if the platform defines a PLATFORM_SCHEMA, validate against that schema. If not defined, it will validate the config against the PLATFORM_SCHEMA defined in the component. Any configuration that references non existing platforms or contains invalid config will be removed.
|
||||
|
||||
The following `configuration.yaml`:
|
||||
|
||||
```yaml
|
||||
unrelated_component:
|
||||
some_key: some_value
|
||||
|
||||
switch:
|
||||
platform: example1
|
||||
|
||||
switch living room:
|
||||
- platform: example2
|
||||
some_config: true
|
||||
- platform: invalid_platform
|
||||
```
|
||||
|
||||
will be passed to the component as
|
||||
|
||||
```python
|
||||
{
|
||||
"unrelated_component": {
|
||||
"some_key": "some_value"
|
||||
},
|
||||
"switch": [
|
||||
{
|
||||
"platform": "example1"
|
||||
},
|
||||
{
|
||||
"platform": "example2,
|
||||
"some_config": True
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
@ -0,0 +1,29 @@
|
||||
---
|
||||
title: Checklist for creating a component
|
||||
id: version-0.72-creating_component_code_review
|
||||
original_id: creating_component_code_review
|
||||
---
|
||||
|
||||
A checklist of things to do when you're adding a new component.
|
||||
|
||||
> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them!
|
||||
|
||||
### 1. Requirements
|
||||
|
||||
1. Requirement version pinned: `REQUIREMENTS = ['phue==0.8.1']`
|
||||
2. We no longer want requirements hosted on GitHub. Please upload to PyPi.
|
||||
3. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly.
|
||||
|
||||
### 2. Configuration
|
||||
|
||||
1. Voluptuous schema present for config validation
|
||||
2. Default parameters specified in voluptuous schema, not in `setup(…)`
|
||||
3. Schema using as many generic config keys as possible from `homeassistant.const`
|
||||
4. If your component has platforms, define a `PLATFORM_SCHEMA` instead of a `CONFIG_SCHEMA`.
|
||||
5. If using a `PLATFORM_SCHEMA` to be used with `EntityComponent`, import base from `homeassistant.helpers.config_validation`
|
||||
6. Never depend on users adding things to `customize` to configure behavior inside your component.
|
||||
|
||||
### 3. Component/platform communication
|
||||
|
||||
1. If you need to share global data with platforms, use the dictionary `hass.data`. `hass.data[DATA_XY]` while `XY` is the component is preferred over `hass.data[DOMAIN]`.
|
||||
2. If the component fetches data that causes its related platform entities to update, you can notify them using the dispatcher code in `homeassistant.helpers.dispatcher`.
|
@ -0,0 +1,51 @@
|
||||
---
|
||||
title: Requirements & Dependencies
|
||||
id: version-0.72-creating_component_deps_and_reqs
|
||||
original_id: creating_component_deps_and_reqs
|
||||
---
|
||||
|
||||
Home Assistant allows components and platforms to specify their dependencies and requirements using the variables `DEPENDENCIES` and `REQUIREMENTS`. Both are lists that contain strings.
|
||||
|
||||
## Dependencies
|
||||
|
||||
Dependencies are other Home Assistant components that should be setup before the platform is loaded. An example is the MQTT sensor component, which requires an active connection to an MQTT broker. If Home Assistant is unable to load and setup the MQTT component, it will not setup the MQTT sensor component.
|
||||
|
||||
```python
|
||||
DEPENDENCIES = ['mqtt']
|
||||
```
|
||||
|
||||
## Requirements
|
||||
|
||||
Requirements are Python libraries or modules that you would normally install using `pip` for your component. Home Assistant will try to install the requirements into the `deps` subdirectory of the Home Assistant [configuration directory](https://www.home-assistant.io/docs/configuration/) if you are not using a `venv` or in something like `path/to/venv/lib/python3.6/site-packages` if you running in a virtual environment. This will make sure that all requirements are present at startup. If steps fails like missing packages for the compilation of a module or other install errors, the component will fail to load.
|
||||
|
||||
Requirements is a list of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v0.6.12:
|
||||
|
||||
```python
|
||||
REQUIREMENTS = ['pychromecast==0.6.12']
|
||||
```
|
||||
|
||||
During development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using pychromecast as an example:
|
||||
|
||||
* `pip install pychromecast==0.6.13 --target ~/.homeassistant/deps`
|
||||
* `hass --skip-pip`
|
||||
|
||||
This will use the specified version, and prevent Home Assistant from trying to override it with what is currently in `REQUIREMENTS`.
|
||||
|
||||
If you need to make changes to a requirement to support your component, it's also possible to `pip install` from a checkout of the requirement.
|
||||
|
||||
* `git clone https://github.com/balloob/pychromecast.git`
|
||||
* `pip install ./pychromecast`
|
||||
* `hass --skip-pip`
|
||||
|
||||
For testing and development purposes you can also to point to a hosted package in the form of an archive (zip/tar.gz) file as a requirement. GitHub provides archive files for a specific branch, release or even a specific commit. To do that the string in `REQUIREMENTS` needs to be composed of two parts:
|
||||
|
||||
* an URL pointing to the archive file (e.g. `https://github.com/my/repo/archive/branch-x.zip`)
|
||||
* a hashtag and `pip` string (as described above) to declare what package and version that archive file contains
|
||||
|
||||
Note: Components and platforms included in Home Assistant should point to published PyPI packages. This ensures that the unit tests will not be slowed down as they can be cached.
|
||||
|
||||
For example, the Neato robot vacuum components specifies the v.0.0.5 release on GitHub as a requirement that gets installed as pybotvac version 0.0.5 (`pybotvac==0.0.5`).
|
||||
|
||||
```python
|
||||
REQUIREMENTS = ['https://github.com/jabesq/pybotvac/archive/v0.0.5.zip#pybotvac==0.0.5']
|
||||
```
|
@ -0,0 +1,53 @@
|
||||
---
|
||||
title: Component Discovery
|
||||
id: version-0.72-creating_component_discovery
|
||||
original_id: creating_component_discovery
|
||||
---
|
||||
|
||||
> This option is only available for built-in components.
|
||||
|
||||
Home Assistant has a discovery service running in the background to discover new devices. Whenever a new device is discovered, a `SERVICE_DISCOVERED` event will be fired with the found service and the information. The `discovery` component has some knowledge about which components handle which type of services and will ensure those are loaded and listening before firing the `SERVICE_DISCOVERED` event.
|
||||
|
||||
### Add discovery instructions
|
||||
|
||||
Device discovery for Home Assistant has been extracted into an external library called [NetDisco](https://github.com/home-assistant/netdisco). This library is integrated using [the `discovery` component](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery.py) and scans the network in intervals for uPnP and zeroconf/mDNS services.
|
||||
|
||||
To have your device be discovered, you will have to extend the NetDisco library to be able to find your device. This is done by adding a new discoverable. [See the repository for examples of existing discoverable.](https://github.com/home-assistant/netdisco/tree/master/netdisco/discoverables)
|
||||
|
||||
### Listening to `SERVICE_DISCOVERED` events
|
||||
|
||||
From your component, you will have to set up the listening for specific services. Given below is an example how one would listen for a discovered AwesomeDevice:
|
||||
|
||||
```python
|
||||
from homeassistant.components.discovery import SERVICE_AWESOMEDEVICE
|
||||
from homeassistant.helpers import discovery
|
||||
|
||||
DOMAIN = 'awesomedevice'
|
||||
|
||||
DEPENDENCIES = ['http']
|
||||
|
||||
def setup(hass, config):
|
||||
cfg = config.get(DOMAIN)
|
||||
|
||||
def device_discovered(service, info):
|
||||
""" Called when a Awesome device has been discovered. """
|
||||
print("Discovered a new Awesome device: {}".format(info))
|
||||
|
||||
discovery.listen(
|
||||
hass, SERVICE_AWESOMEDEVICE, device_discovered)
|
||||
|
||||
return True
|
||||
```
|
||||
|
||||
### Auto-loading your component upon discovery
|
||||
|
||||
The `discovery` component is capable of setting up your components before firing the `EVENT_PLATFORM_DISCOVERED` event. To do this you will have to update the [`SERVICE_HANDLERS`](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery.py#L40) constant in [the `discovery` component](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/components/discovery.py):
|
||||
|
||||
```python
|
||||
SERVICE_AWESOMEDEVICE = 'awesomedevice'
|
||||
|
||||
SERVICE_HANDLERS = {
|
||||
...
|
||||
SERVICE_AWESOMEDEVICE: ('awesomedevice', None),
|
||||
}
|
||||
```
|
@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Handling events
|
||||
id: version-0.72-creating_component_events
|
||||
original_id: creating_component_events
|
||||
---
|
||||
|
||||
Home Assistant has different ways of responding to events that occur in Home Assistant. These have been organized in [helper methods](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/event.py). Examples are `track_state_change`, `track_point_in_time`, `track_time_change`.
|
@ -0,0 +1,72 @@
|
||||
---
|
||||
title: Generic Platform Discovery
|
||||
id: version-0.72-creating_component_generic_discovery
|
||||
original_id: creating_component_generic_discovery
|
||||
---
|
||||
|
||||
New controller or hub components often need to add platforms in sub-components (i.e. Lights & Switches) without additional configuration.
|
||||
This can be achieved using the `load_platform` or `async_load_platform` methods from `homeassistant.helpers.discovery`:
|
||||
|
||||
```python
|
||||
def load_platform(hass, component, platform, discovered=None, hass_config=None)
|
||||
```
|
||||
|
||||
From more info on how this works, refer to the [load_platform](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/discovery.py#L136) method.
|
||||
|
||||
### Example
|
||||
|
||||
Say you need to implement your new MyFlashyHub that controls both Switches & Lights, you can follow these steps:
|
||||
|
||||
Configuration required for your new hub component:
|
||||
|
||||
```yaml
|
||||
myflashyhub:
|
||||
example: setting
|
||||
```
|
||||
|
||||
The source for your component can be located in your configuration directory for now:
|
||||
|
||||
```bash
|
||||
~/.homeassistant/custom_components/myflashyhub.py
|
||||
~/.homeassistant/custom_components/light/myflashyhub.py
|
||||
~/.homeassistant/custom_components/switch/myflashyhub.py
|
||||
```
|
||||
|
||||
In the hub component `myflashyhub.py` you can call your light and switch components. To pass any non-serializable information to the platforms in the sub-component, you can use a global variable.
|
||||
|
||||
```python
|
||||
from homeassistant.helpers.discovery import load_platform
|
||||
DOMAIN = 'myflashyhub'
|
||||
|
||||
DATA_MFH = 'MFH'
|
||||
|
||||
def setup(hass, config):
|
||||
"""Your controller/hub specific code."""
|
||||
hass.data[DATA_MFH] = SomeObjectToInitialiseGlobal()
|
||||
|
||||
#--- snip ---
|
||||
load_platform(hass, 'light', DOMAIN)
|
||||
load_platform(hass, 'switch', DOMAIN, {'optional': 'arguments'})
|
||||
```
|
||||
|
||||
Add your custom device specific code to the `setup_platform` method in `light/myflashyhub.py` and `switch/myflashyhub`.
|
||||
|
||||
```python
|
||||
import custom_components.myflashyhub as myflashyhub
|
||||
|
||||
# 'switch' will receive discovery_info={'optional': 'arguments'}
|
||||
# as passed in above. 'light' will receive discovery_info=None
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Your switch/light specific code."""
|
||||
# You can now use hass.data[myflashyhub.DATA_MFH]
|
||||
```
|
||||
|
||||
|
||||
The `load_platform` method allows the platforms to be loaded without the need for any additional platform entries in your `configuration.yaml` file, which normally would have been:
|
||||
|
||||
```yaml
|
||||
#light:
|
||||
# platform: myflashyhub
|
||||
#switch:
|
||||
# platform: myflashyhub
|
||||
```
|
@ -0,0 +1,21 @@
|
||||
---
|
||||
title: Creating components
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-creating_component_index
|
||||
original_id: creating_component_index
|
||||
---
|
||||
|
||||
Alright, you're ready to make your first component. AWESOME. Don't worry, we've tried hard to keep it as easy as possible.
|
||||
|
||||
### Example component
|
||||
|
||||
Add `hello_state:` to your `configuration.yaml` file and create a file `<config_dir>/custom_components/hello_state.py` with the below code to test it locally.
|
||||
|
||||
```python
|
||||
DOMAIN = 'hello_state'
|
||||
|
||||
def setup(hass, config):
|
||||
hass.states.set('hello.world', 'Paulus')
|
||||
|
||||
return True
|
||||
```
|
@ -0,0 +1,16 @@
|
||||
---
|
||||
title: Loading your components
|
||||
id: version-0.72-creating_component_loading
|
||||
original_id: creating_component_loading
|
||||
---
|
||||
|
||||
A component will be loaded on start if a section (ie. `light:`) for it exists in the config file. A component can also be loaded if another component is loaded that depends on it. When loading a component Home Assistant will check the following paths:
|
||||
|
||||
* `<config directory>/custom_components/<component name>`
|
||||
* `homeassistant/components/<component name>` (built-in components)
|
||||
|
||||
Once loaded, a component will only be setup if all dependencies can be loaded and are able to setup. Keep an eye on the logs to see if your component could be loaded and initialized.
|
||||
|
||||
> You can override a built-in component by having a component with the same name in your <code>config/custom_components</code> folder. If the built-in component is inside a subfolder, take care to place your customization in a folder with the same name in <code>config/custom_components/*folder*</code>. Note that overriding built-in components is not recommended and will probably break things!
|
||||
|
||||
> Home Assistant will use the directory that contains your config file as the directory that holds your customizations. By default this is the <code>config</code> folder in your current work directory. You can use a different folder by running Home Assistant with the --config argument: <code>python3 homeassistant --config /YOUR/CONFIG/PATH/</code>.
|
@ -0,0 +1,17 @@
|
||||
---
|
||||
title: Handling states
|
||||
id: version-0.72-creating_component_states
|
||||
original_id: creating_component_states
|
||||
---
|
||||
|
||||
It is the responsibility of the component to maintain the states of the devices in your domain. Each device should be a single state and, if possible, a group should be provided that tracks the combined state of the devices.
|
||||
|
||||
A state can have several attributes that will help the frontend in displaying your state:
|
||||
|
||||
- `friendly_name`: this name will be used as the name of the device
|
||||
- `entity_picture`: this picture will be shown instead of the domain icon
|
||||
- `unit_of_measurement`: this will be appended to the state in the interface
|
||||
- `hidden`: This is a suggestion to the frontend on if the state should be hidden
|
||||
|
||||
These attributes are defined in [homeassistant.helpers.entity](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/entity.py#L180).
|
||||
|
@ -0,0 +1,72 @@
|
||||
---
|
||||
title: Checklist for creating a platform
|
||||
id: version-0.72-creating_platform_code_review
|
||||
original_id: creating_platform_code_review
|
||||
---
|
||||
|
||||
A checklist of things to do when you're adding a new platform.
|
||||
|
||||
> Not all existing platforms follow the requirements in this checklist. This cannot be used as a reason to not follow them!
|
||||
|
||||
### 1. Requirements
|
||||
|
||||
1. Requirement version should be pinned: `REQUIREMENTS = ['phue==0.8.1']`
|
||||
2. We no longer want requirements hosted on GitHub. Please upload to PyPi.
|
||||
3. Requirements should only be imported inside functions. This is necessary because requirements are installed on the fly.
|
||||
|
||||
### 2. Dependencies
|
||||
|
||||
1. If you depend on a component for the connection, add it to your dependencies: `DEPENDENCIES = ['nest']`
|
||||
|
||||
### 3. Configuration
|
||||
|
||||
1. Voluptuous schema present for config validation
|
||||
2. Voluptuous schema extends schema from component<br>(e.g., `light.hue.PLATFORM_SCHEMA` extends `light.PLATFORM_SCHEMA`)
|
||||
3. Default parameters specified in voluptuous schema, not in `setup_platform(…)`
|
||||
4. Your `PLATFORM_SCHEMA` should use as many generic config keys as possible from `homeassistant.const`
|
||||
```python
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.const import CONF_FILENAME, CONF_HOST
|
||||
from homeassistant.components.light import PLATFORM_SCHEMA
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
CONF_ALLOW_UNREACHABLE = 'allow_unreachable'
|
||||
DEFAULT_UNREACHABLE = False
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
vol.Optional(CONF_ALLOW_UNREACHABLE,
|
||||
default=DEFAULT_UNREACHABLE): cv.boolean,
|
||||
vol.Optional(CONF_FILENAME): cv.string,
|
||||
})
|
||||
```
|
||||
5. Never depend on users adding things to `customize` to configure behavior inside your platform.
|
||||
|
||||
### 4. Setup Platform
|
||||
|
||||
1. Test if passed in info (user/pass/host etc.) works.
|
||||
2. Group your calls to `add_devices` if possible.
|
||||
3. If platform adds extra services, format should be `<component>.<platform>_<service name>`.
|
||||
|
||||
### 5. Entity
|
||||
|
||||
1. Extend entity from component, e.g., `class HueLight(Light)`.
|
||||
2. Avoid passing in `hass` as a parameter to the entity. When the entity has been added to Home Assistant, `hass` will be set on the entity by the helper in entity_platform.py. This means you can access `hass` as `self.hass` inside the entity.
|
||||
3. Do not call `update()` in constructor, use `add_devices(devices, True)` instead.
|
||||
4. Do not do any I/O inside properties. Cache values inside `update()` instead.
|
||||
5. The state and/or attributes should not contain relative time since something happened. Instead it should store UTC timestamps.
|
||||
|
||||
### 6. Communication with devices/services
|
||||
|
||||
1. All API specific code has to be part of a third party library hosted on PyPi. Home Assistant should only interact with objects and not make direct calls to the API.
|
||||
|
||||
```python
|
||||
# bad
|
||||
status = requests.get(url('/status'))
|
||||
|
||||
# good
|
||||
from phue import Bridge
|
||||
bridge = Bridge(…)
|
||||
status = bridge.status()
|
||||
```
|
@ -0,0 +1,119 @@
|
||||
---
|
||||
title: Example light platform
|
||||
id: version-0.72-creating_platform_example_light
|
||||
original_id: creating_platform_example_light
|
||||
---
|
||||
|
||||
This example is for adding support for the imaginary Awesome Lights. It shows the different best practices for developing a platform.
|
||||
|
||||
Similar to Example Sensor Platform, copy the code below, and create it as a file in `<config_dir>/custom_components/light/awesomelights.py`.
|
||||
|
||||
Add the following to your configuration.yaml:
|
||||
|
||||
```yaml
|
||||
light:
|
||||
- platform: awesomelights
|
||||
host: HOST_HERE
|
||||
username: USERNAME_HERE
|
||||
password: PASSWORD_HERE_OR_secrets.yaml
|
||||
```
|
||||
|
||||
Note the `platform` name matches the filename for the source code.
|
||||
|
||||
```python
|
||||
import logging
|
||||
|
||||
import voluptuous as vol
|
||||
|
||||
# Import the device class from the component that you want to support
|
||||
from homeassistant.components.light import ATTR_BRIGHTNESS, Light, PLATFORM_SCHEMA
|
||||
from homeassistant.const import CONF_HOST, CONF_USERNAME, CONF_PASSWORD
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
# Home Assistant depends on 3rd party packages for API specific code.
|
||||
REQUIREMENTS = ['awesome_lights==1.2.3']
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
# Validation of the user's configuration
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
vol.Required(CONF_HOST): cv.string,
|
||||
vol.Optional(CONF_USERNAME, default='admin'): cv.string,
|
||||
vol.Optional(CONF_PASSWORD): cv.string,
|
||||
})
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup the Awesome Light platform."""
|
||||
import awesomelights
|
||||
|
||||
# Assign configuration variables. The configuration check takes care they are
|
||||
# present.
|
||||
host = config.get(CONF_HOST)
|
||||
username = config.get(CONF_USERNAME)
|
||||
password = config.get(CONF_PASSWORD)
|
||||
|
||||
# Setup connection with devices/cloud
|
||||
hub = awesomelights.Hub(host, username, password)
|
||||
|
||||
# Verify that passed in configuration works
|
||||
if not hub.is_valid_login():
|
||||
_LOGGER.error("Could not connect to AwesomeLight hub")
|
||||
return
|
||||
|
||||
# Add devices
|
||||
add_devices(AwesomeLight(light) for light in hub.lights())
|
||||
|
||||
|
||||
|
||||
class AwesomeLight(Light):
|
||||
"""Representation of an Awesome Light."""
|
||||
|
||||
def __init__(self, light):
|
||||
"""Initialize an AwesomeLight."""
|
||||
self._light = light
|
||||
self._name = light.name
|
||||
self._state = None
|
||||
self._brightness = None
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the display name of this light."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def brightness(self):
|
||||
"""Return the brightness of the light.
|
||||
|
||||
This method is optional. Removing it indicates to Home Assistant
|
||||
that brightness is not supported for this light.
|
||||
"""
|
||||
return self._brightness
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return true if light is on."""
|
||||
return self._state
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Instruct the light to turn on.
|
||||
|
||||
You can skip the brightness part if your light does not support
|
||||
brightness control.
|
||||
"""
|
||||
self._light.brightness = kwargs.get(ATTR_BRIGHTNESS, 255)
|
||||
self._light.turn_on()
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Instruct the light to turn off."""
|
||||
self._light.turn_off()
|
||||
|
||||
def update(self):
|
||||
"""Fetch new state data for this light.
|
||||
|
||||
This is the only method that should fetch new data for Home Assistant.
|
||||
"""
|
||||
self._light.update()
|
||||
self._state = self._light.is_on()
|
||||
self._brightness = self._light.brightness
|
||||
```
|
@ -0,0 +1,61 @@
|
||||
---
|
||||
title: Example sensor platform
|
||||
id: version-0.72-creating_platform_example_sensor
|
||||
original_id: creating_platform_example_sensor
|
||||
---
|
||||
|
||||
This is a minimum implementation of a platform for the sensor component.
|
||||
|
||||
### Installation
|
||||
|
||||
Copy the code below and create it as a file in `<config_dir>/custom_components/sensor/example.py`.
|
||||
|
||||
Add the following to your `configuration.yaml` file:
|
||||
|
||||
```yaml
|
||||
# Example configuration.yaml entry
|
||||
sensor:
|
||||
platform: example
|
||||
```
|
||||
|
||||
### Code
|
||||
|
||||
```python
|
||||
from homeassistant.const import TEMP_CELSIUS
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
"""Setup the sensor platform."""
|
||||
add_devices([ExampleSensor()])
|
||||
|
||||
|
||||
class ExampleSensor(Entity):
|
||||
"""Representation of a Sensor."""
|
||||
|
||||
def __init__(self):
|
||||
"""Initialize the sensor."""
|
||||
self._state = None
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return 'Example Temperature'
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
"""Return the state of the sensor."""
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
"""Return the unit of measurement."""
|
||||
return TEMP_CELSIUS
|
||||
|
||||
def update(self):
|
||||
"""Fetch new state data for the sensor.
|
||||
|
||||
This is the only method that should fetch new data for Home Assistant.
|
||||
"""
|
||||
self._state = 23
|
||||
```
|
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: Adding support for a new platform
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-creating_platform_index
|
||||
original_id: creating_platform_index
|
||||
---
|
||||
|
||||
Components that interact with devices are called "[Entity Components](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/entity_component.py)." They are structured in core and platform logic, which means different brands can use the same logic to handle a light.
|
||||
|
||||
For example, the built-in `switch` component consists of various platforms in [`homeassistant/components/switch/`](https://github.com/home-assistant/home-assistant/tree/master/homeassistant/components/switch). The file `__init__.py` contains the core logic of all platforms and the `vendor_name.py` files contain only the relevant platform code.
|
||||
|
||||
If you're planning to add support for a new type of device to an existing component, you can get away with only writing platform logic. Have a look at how the component works with other platforms and create a similar file for the platform that you want to add:
|
||||
|
||||
- [Example sensor platform](creating_platform_example_sensor.md): hello world of platforms.
|
||||
- [Example light platform](creating_platform_example_light.md): showing best practices.
|
||||
|
||||
### Interfacing with devices
|
||||
|
||||
One Home Assistant rule is that platform logic should never interface directly with devices. Instead, use a third-party Python 3 library. This way, Home Assistant can share code with the Python community and keep the project maintainable.
|
||||
|
||||
To integrate the third-party library, create an [Entity class](https://github.com/home-assistant/home-assistant/blob/dev/homeassistant/helpers/entity.py) for your device. Entities are Home Assistant's representations of lights, switches, sensors, etc. and are derived from the [Entity Abstract Class](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/entity.py). This abstract class contains logic for integrating most standard features into your entities, such as visibility, entity IDs, updates, and much more.
|
||||
|
||||
### Requirements and dependencies
|
||||
|
||||
Platforms can specify dependencies and requirements [the same way as components](creating_component_deps_and_reqs.md):
|
||||
|
||||
```python
|
||||
REQUIREMENTS = ['some-package==2.0.0', 'some-other-package==2.5.0']
|
||||
DEPENDENCIES = ['mqtt']
|
||||
```
|
||||
|
190
website/versioned_docs/version-0.72/data_entry_flow_index.md
Normal file
190
website/versioned_docs/version-0.72/data_entry_flow_index.md
Normal file
@ -0,0 +1,190 @@
|
||||
---
|
||||
title: Data Entry Flow
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-data_entry_flow_index
|
||||
original_id: data_entry_flow_index
|
||||
---
|
||||
|
||||
Data Entry Flow is a data entry framework that is part of Home Assistant. Data entry is done via data entry flows. A flow can represent a simple login form or a multi-step setup wizard for a component. A Flow Manager is managing all flows that are in progress and handles creation of new flows.
|
||||
|
||||
Data Entry Flow is being used in Home Assistant to create config entries.
|
||||
|
||||
## Flow Manager
|
||||
|
||||
This is the class that manages the flows that are in progress. When instantiating one, you pas in two async callbacks:
|
||||
|
||||
```python
|
||||
async def async_create_flow(handler, source=source, data=data)
|
||||
```
|
||||
|
||||
The manager delegates instantiating of config flow handlers to this async callback. This allows the parent of the manager to define their own way of finding handlers and preparing a handler for instantiation. For example, in the case of the config entry manager, it will make sure that the dependencies and requirements are setup.
|
||||
|
||||
```python
|
||||
async def async_finish_flow(result)
|
||||
```
|
||||
|
||||
This async callback is called when a flow is finished. The result is a dictionary that looks like this:
|
||||
|
||||
```python
|
||||
{
|
||||
# Data schema version of the entry
|
||||
'version': 2,
|
||||
# The result type of the flow
|
||||
'type': RESULT_TYPE_CREATE_ENTRY,
|
||||
# the id of the flow
|
||||
'flow_id': 'abcdfgh1234,
|
||||
# handler name
|
||||
'handler': 'hue',
|
||||
# title and data as created by the handler
|
||||
'title': 'Some title',
|
||||
'data': {
|
||||
'some': 'data'
|
||||
},
|
||||
# Source that instantiated the flow
|
||||
'source': self.source,
|
||||
}
|
||||
```
|
||||
|
||||
## Config Flow Handler
|
||||
|
||||
Config flow handlers will handle a single flow. A flow contains 1 or more steps. When a flow is instantiated by the user, the `init` step will be called. Each step has three different possible results: "Show Form", "Abort" and "Create Entry".
|
||||
|
||||
At a minimum, each config flow handler will have to define a version number and a step. This doens't have to be `init`, as different steps will be called when instantiated by a non-user (ie discovery).
|
||||
|
||||
The bare minimum config flow:
|
||||
|
||||
```python
|
||||
from homeassistant import data_entry_flow
|
||||
|
||||
class ExampleConfigFlow(data_entry_flow.FlowHandler):
|
||||
|
||||
# The schema version of the entries that it creates
|
||||
# Home Assistant will call your migrate method if the version changes
|
||||
# (this is not implemented yet)
|
||||
VERSION = 1
|
||||
|
||||
async def async_step_init(self, user_input=None):
|
||||
# Do something
|
||||
```
|
||||
|
||||
### Show Form
|
||||
|
||||
This result type will show a form to the user to fill in. You define the current step, the schema of the data (using voluptuous) and optionally a dictionary of errors. Title and description of the step will be provided via the translation file. Where this is defined depends on the context of the data entry flow.
|
||||
|
||||
```python
|
||||
class ExampleConfigFlow(data_entry_flow.FlowHandler):
|
||||
|
||||
async def async_step_init(self, user_input=None):
|
||||
# Use OrderedDict to guarantee order of the form shown to the user
|
||||
data_schema = OrderedDict()
|
||||
data_schema[vol.Required('username')] = str
|
||||
data_schema[vol.Required('password')] = str
|
||||
|
||||
return self.async_show_form(
|
||||
step_id='init',
|
||||
data_schema=vol.Schema(data_schema)
|
||||
)
|
||||
```
|
||||
|
||||
After the user has filled in the form, the step method will be called again and the user input is passed in. Your step will only be called if the user input passes your data schema. When the user passes in data, you will have to do extra validation of the data. For example, you can verify that the passed in username and password are valid.
|
||||
|
||||
If something is wrong, you can return a dictionary with errors. Each key in the error dictionary refers to a field name that contains the error. Use the key `base` if you want to show an error unrelated to a specific field. The specified errors need to refer to a key in a translation file.
|
||||
|
||||
```python
|
||||
class ExampleConfigFlow(data_entry_flow.FlowHandler):
|
||||
|
||||
async def async_step_init(self, user_input=None):
|
||||
errors = {}
|
||||
if user_input is not None:
|
||||
# Validate user input
|
||||
valid = await is_valid(user_input)
|
||||
if valid:
|
||||
# See next section on create entry usage
|
||||
return self.create_entry(…)
|
||||
|
||||
errors['base'] = 'auth_error'
|
||||
|
||||
# Use OrderedDict to guarantee order of the form shown to the user
|
||||
data_schema = OrderedDict()
|
||||
data_schema[vol.Required('username')] = str
|
||||
data_schema[vol.Required('password')] = str
|
||||
|
||||
return self.async_show_form(
|
||||
step_id='init',
|
||||
data_schema=vol.Schema(data_schema),
|
||||
errors=errors
|
||||
)
|
||||
```
|
||||
|
||||
#### Multi-step flows
|
||||
|
||||
If the user input passes validation, you can again return one of the three
|
||||
return values. If you want to navigate the user to the next step, return the
|
||||
return value of that step:
|
||||
|
||||
```python
|
||||
class ExampleConfigFlow(data_entry_flow.FlowHandler):
|
||||
|
||||
async def async_step_init(self, user_input=None):
|
||||
errors = {}
|
||||
if user_input is not None:
|
||||
# Validate user input
|
||||
valid = await is_valid(user_input)
|
||||
if valid:
|
||||
# Store info to use in next step
|
||||
self.init_info = user_input
|
||||
# Return the form of the next step
|
||||
return await self.async_step_account()
|
||||
|
||||
…
|
||||
```
|
||||
|
||||
### Create Entry
|
||||
|
||||
When the result is "Create Entry", an entry will be created and passed to the parent of the flow manager. A success message is shown to the user and the flow is finished. You create an entry by passing a title and data. The title can be used in the UI to indicate to the user which entry it is. Data can be any data type, as long as it is JSON serializable.
|
||||
|
||||
```python
|
||||
class ExampleConfigFlow(data_entry_flow.FlowHandler):
|
||||
|
||||
async def async_step_init(self, user_input=None):
|
||||
return self.create_entry(
|
||||
title='Title of the entry',
|
||||
data={
|
||||
'something_special': user_input['username']
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
### Abort
|
||||
|
||||
When a flow cannot be finished, you need to abort it. This will finish the flow and inform the user that the flow has finished. Reasons for a flow to not be able to finish can be that a device is already configured or not compatible with Home Assistant.
|
||||
|
||||
```python
|
||||
class ExampleConfigFlow(data_entry_flow.FlowHandler):
|
||||
|
||||
async def async_step_init(self, user_input=None):
|
||||
return self.async_abort(
|
||||
reason='not_supported'
|
||||
)
|
||||
```
|
||||
|
||||
## Translations
|
||||
|
||||
Data entry flows depend on translations for showing the text in the forms. It depends on the parent of a data entry flow manager where this is stored.
|
||||
|
||||
## Initializing a config flow from an external source
|
||||
|
||||
You might want to initialize a config flow programmatically. For example, if we discover a device on the network that requires user interaction to finish setup. To do so, pass a source parameter and optional user input when initializing a flow:
|
||||
|
||||
```python
|
||||
await flow_mgr.async_init('hue', source=data_entry_flow.SOURCE_DISCOVERY, data=discovery_info)
|
||||
```
|
||||
|
||||
The config flow handler will not start with the `init` step. Instead, it will be instantiated with a step name equal to the source. The step should follow the same return values as a normal step.
|
||||
|
||||
```python
|
||||
class ExampleConfigFlow(data_entry_flow.FlowHandler):
|
||||
|
||||
async def async_step_discovery(self, info):
|
||||
# Handle discovery info
|
||||
```
|
30
website/versioned_docs/version-0.72/dev_101_config.md
Normal file
30
website/versioned_docs/version-0.72/dev_101_config.md
Normal file
@ -0,0 +1,30 @@
|
||||
---
|
||||
title: Using Config
|
||||
id: version-0.72-dev_101_config
|
||||
original_id: dev_101_config
|
||||
---
|
||||
|
||||
Based on where you are in the code, `config` can mean various things.
|
||||
|
||||
### On the hass object
|
||||
|
||||
On the hass object is an instance of the Config class. The Config class contains the users preferred units, the path to the config directory and which components are loaded. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config)
|
||||
|
||||
### Config passed into component setup
|
||||
|
||||
The `config` parameter passed to a component setup is a dictionary containing all of the user supplied configuration. The keys of the dictionary are the component names and the value is another dictionary with the component configuration.
|
||||
|
||||
The object will have already been validated using your `CONFIG_SCHEMA` or `PLATFORM_SCHEMA` if available. If you have defined a `PLATFORM_SCHEMA`, all references to your component (ie `light 2:` etc) will have been changed to be accessible as a list under `config[DOMAIN]`.
|
||||
|
||||
If your configuration file contains the following lines:
|
||||
|
||||
```yaml
|
||||
example:
|
||||
host: paulusschoutsen.nl
|
||||
```
|
||||
|
||||
Then in the setup method of your component you will be able to refer to `config['example']['host']` to get the value `paulusschoutsen.nl`.
|
||||
|
||||
### Passed into platform setup
|
||||
|
||||
The `config` parameter passed to a platform setup function is only the config for that specific platform.
|
57
website/versioned_docs/version-0.72/dev_101_events.md
Normal file
57
website/versioned_docs/version-0.72/dev_101_events.md
Normal file
@ -0,0 +1,57 @@
|
||||
---
|
||||
title: Using Events
|
||||
id: version-0.72-dev_101_events
|
||||
original_id: dev_101_events
|
||||
---
|
||||
|
||||
The core of Home Assistant is driven by events. That means that if you want to respond to something happening, you'll have to respond to events. Most of the times you won't interact directly with the event system but use one of the [event listener helpers][helpers].
|
||||
|
||||
The event system is very flexible. There are no limitations on the event type, as long as it's a string. Each event can contain data. The data is a dictionary that can contain any data as long as it's JSON serializable. This means that you can use number, string, dictionary and list.
|
||||
|
||||
[List of events that Home Assistant fires.][object]
|
||||
|
||||
## Firing events
|
||||
|
||||
To fire an event, you have to interact with the event bus. The event bus is available on the Home Assistant instance as `hass.bus`.
|
||||
|
||||
Example component that will fire an event when loaded.
|
||||
|
||||
```python
|
||||
DOMAIN = 'hello_event'
|
||||
|
||||
def setup(hass, config):
|
||||
"""Set up is called when Home Assistant is loading our component."""
|
||||
|
||||
# Fire event my_cool_event with event data answer=42
|
||||
hass.bus.fire('my_cool_event', {
|
||||
'answer': 42
|
||||
})
|
||||
```
|
||||
|
||||
## Listening to events
|
||||
|
||||
Most of the times you'll not be firing events but instead listen to events. For example, the state change of an entity is broadcasted as an event.
|
||||
|
||||
```python
|
||||
DOMAIN = 'hello_event'
|
||||
|
||||
def setup(hass, config):
|
||||
"""Set up is called when Home Assistant is loading our component."""
|
||||
count = 0
|
||||
|
||||
# Listener to handle fired events
|
||||
def handle_event(event):
|
||||
nonlocal count
|
||||
count += 1
|
||||
print('Total events received:', count)
|
||||
|
||||
# Listen for when my_cool_event is fired
|
||||
hass.bus.listen('my_cool_event', handle_event)
|
||||
```
|
||||
|
||||
### Helpers
|
||||
|
||||
Home Assistant comes with a lot of bundled helpers to listen to specific types of event. There are helpers to track a point in time, to track a time interval, a state change or the sun set. [See available methods.][helpers]
|
||||
|
||||
[helpers]: https://dev-docs.home-assistant.io/en/master/api/helpers.html#module-homeassistant.helpers.event
|
||||
[object]: https://www.home-assistant.io/docs/configuration/events/
|
32
website/versioned_docs/version-0.72/dev_101_hass.md
Normal file
32
website/versioned_docs/version-0.72/dev_101_hass.md
Normal file
@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Hass object
|
||||
id: version-0.72-dev_101_hass
|
||||
original_id: dev_101_hass
|
||||
---
|
||||
|
||||
While developing Home Assistant you will see a variable that is everywhere: `hass`. This is the Home Assistant instance that will give you access to all the various parts of the system.
|
||||
|
||||
### The `hass` object
|
||||
|
||||
The Home Assistant instance contains four objects to help you interact with the system.
|
||||
|
||||
| Object | Description |
|
||||
| ------ | ----------- |
|
||||
| `hass` | This is the instance of Home Assistant. Allows starting, stopping and enqueing new jobs. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.HomeAssistant)
|
||||
| `hass.config` | This is the core configuration of Home Assistant exposing location, temperature preferences and config directory path. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.Config)
|
||||
| `hass.states` | This is the StateMachine. It allows you to set states and track when they are changed. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.StateMachine) |
|
||||
| `hass.bus` | This is the EventBus. It allows you to trigger and listen for events. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.EventBus) |
|
||||
| `hass.services` | This is the ServiceRegistry. It allows you to register services. [See available methods.](https://dev-docs.home-assistant.io/en/master/api/core.html#homeassistant.core.ServiceRegistry) |
|
||||
|
||||
### Where to find `hass`
|
||||
|
||||
Depending on what you're writing, there are different ways the `hass` object is made available.
|
||||
|
||||
**Component**<br>
|
||||
Passed into `setup(hass, config)` or `async_setup(hass, config)`.
|
||||
|
||||
**Platform**<br>
|
||||
Passed into `setup_platform(hass, config, add_devices, discovery_info=None)` or `async_setup_platform(hass, config, async_add_devices, discovery_info=None)`.
|
||||
|
||||
**Entity**<br>
|
||||
Available as `self.hass` once the entity has been added via the `add_devices` callback inside a platform.
|
49
website/versioned_docs/version-0.72/dev_101_index.md
Normal file
49
website/versioned_docs/version-0.72/dev_101_index.md
Normal file
@ -0,0 +1,49 @@
|
||||
---
|
||||
title: Development 101
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-dev_101_index
|
||||
original_id: dev_101_index
|
||||
---
|
||||
|
||||
The goal of development 101 is to get you familiar with the basics of developing for Home Assistant. Before we start, please make sure you familiarize yourself with the [architecture](architecture_index.md).
|
||||
|
||||
To get our code running inside Home Assistant we're going to create a custom component. The first step is to locate your config folder. You can find the path to your config folder by opening the Home Assistant frontend, click on the <img src='/img/dev-tools/about-icon.png' alt='service developer tool icon' class="inline" width="38" />. It's the path after the text "Path to configuration.yaml".
|
||||
|
||||
Inside your configuration directory create a new folder called `custom_components`. It might be that one already exists, that's fine too. This is the folder that Home Assistant will look at when looking for custom code.
|
||||
|
||||
> The Home Assistant API has two variants: a synchronous and an asynchronous version (asyncio). This development course will focus on the synchronous version.
|
||||
|
||||
To verify that everything is working correctly, let's create a small Hello World component. To do so, create a file called `hello_world.py` in your custom components folder. Copy paste the following content to it:
|
||||
|
||||
```python
|
||||
# The domain of your component. Equal to the filename of your component.
|
||||
DOMAIN = "hello_world"
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""Setup the hello_world component."""
|
||||
# States are in the format DOMAIN.OBJECT_ID.
|
||||
hass.states.set('hello_world.Hello_World', 'Works!')
|
||||
|
||||
# Return boolean to indicate that initialization was successfully.
|
||||
return True
|
||||
```
|
||||
|
||||
Last step is to add `hello_world:` entry to your `configuration.yaml` file.
|
||||
|
||||
```yaml
|
||||
# Hello World component
|
||||
hello_world:
|
||||
```
|
||||
|
||||
After running `hass`, we should see log entries stating that `hello_world` component was loaded. What is more, additional state card shall appear within main panel.
|
||||
|
||||
```log
|
||||
2018-04-03 21:44:20 INFO (MainThread) [homeassistant.loader] Loaded hello_world from custom_components.hello_world
|
||||
2018-04-03 21:44:20 INFO (MainThread) [homeassistant.setup] Setting up hello_world
|
||||
```
|
||||
|
||||
<img
|
||||
src='/img/en/frontend/hello-world-state-card.png'
|
||||
alt='State card showing that Hello World component is working as intended.'
|
||||
/>
|
50
website/versioned_docs/version-0.72/dev_101_services.md
Normal file
50
website/versioned_docs/version-0.72/dev_101_services.md
Normal file
@ -0,0 +1,50 @@
|
||||
---
|
||||
title: Using Services
|
||||
id: version-0.72-dev_101_services
|
||||
original_id: dev_101_services
|
||||
---
|
||||
|
||||
This is a simple "hello world" example to show the basics of registering a service. To use this example, create the file `<config dir>/custom_components/hello_service.py` and copy the below example code.
|
||||
|
||||
Services can be called from automation and from the service "Developer tools" in the frontend.
|
||||
|
||||
```python
|
||||
# The domain of your component. Should be equal to the name of your component.
|
||||
DOMAIN = 'hello_service'
|
||||
|
||||
ATTR_NAME = 'name'
|
||||
DEFAULT_NAME = 'World'
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
"""Set up is called when Home Assistant is loading our component."""
|
||||
|
||||
def handle_hello(call):
|
||||
name = call.data.get(ATTR_NAME, DEFAULT_NAME)
|
||||
|
||||
hass.states.set('hello_service.hello', name)
|
||||
|
||||
hass.services.register(DOMAIN, 'hello', handle_hello)
|
||||
|
||||
# Return boolean to indicate that initialization was successfully.
|
||||
return True
|
||||
```
|
||||
|
||||
Load the component by adding the following to your `configuration.yaml`. When your component is loaded, a new service should be available to call.
|
||||
|
||||
```yaml
|
||||
# configuration.yaml entry
|
||||
hello_service:
|
||||
```
|
||||
|
||||
Open the frontend and in the sidebar, click the first icon in the developer tool section. This will open the Call Service developer tool. On the right, find your service and click on it. This will automatically fill in the correct values.
|
||||
|
||||
Pressing "Call Service" will now call your service without any parameters. This will cause your service to create a state with the default name 'World'. If you want to specify the name, you have to specify parameters. Add the following JSON as Service Data and press "Call Service again".
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Planet"
|
||||
}
|
||||
```
|
||||
|
||||
The service will now overwrite the previous state with "Planet".
|
133
website/versioned_docs/version-0.72/dev_101_states.md
Normal file
133
website/versioned_docs/version-0.72/dev_101_states.md
Normal file
@ -0,0 +1,133 @@
|
||||
---
|
||||
title: Using States
|
||||
id: version-0.72-dev_101_states
|
||||
original_id: dev_101_states
|
||||
---
|
||||
|
||||
Home Assistant keeps track of the states of entities in a state machine. The state machine has very few requirements:
|
||||
|
||||
- Each state is related to an entity identified by an entity id. This id is made up of a domain and an object id. For example `light.kitchen_ceiling`. You can make up any combination of domain and object id, even overwriting existing states.
|
||||
- Each state has a primary attribute that describes the state of the entity. In the case of a light this could be for example "on" and "off". You can store anything you want in the state, as long as it's a string (will be converted if it's not).
|
||||
- You can store more information about an entity by setting attributes. Attributes is a dictionary that can contain any data that you want. The only requirement is that it's JSON serializable, so you're limited to numbers, strings, dictionaries and lists.
|
||||
|
||||
[Description of the state object.](https://www.home-assistant.io/docs/configuration/state_object/)
|
||||
|
||||
## Using states in your component
|
||||
|
||||
This is a simple tutorial/example on how to create and set states. We will do our work in a component called "hello_state". The purpose of this component is to display a given text in the frontend.
|
||||
|
||||
To get started, create the file `<config dir>/custom_components/hello_state.py` and copy the below example code.
|
||||
|
||||
```python
|
||||
"""
|
||||
Support for showing text in the frontend.
|
||||
|
||||
For more details about this component, please refer to the documentation at
|
||||
https://home-assistant.io/cookbook/python_component_basic_state/
|
||||
"""
|
||||
import logging
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DOMAIN = 'hello_state'
|
||||
DEPENDENCIES = []
|
||||
|
||||
def setup(hass, config):
|
||||
"""Setup the Hello State component. """
|
||||
_LOGGER.info("The 'hello state' component is ready!")
|
||||
|
||||
return True
|
||||
```
|
||||
|
||||
1. In the file header we decided to add some details: A short description and the link to the documentation.
|
||||
2. We want to do some logging. This means that we import the Python logging module and create an alias.
|
||||
3. The component name is equal to the domain name.
|
||||
4. At the moment this component has no dependencies. For detail check [dependencies](creating_component_deps_and_reqs.md#dependencies) section.
|
||||
5. The `setup` function will take care of the initialization of our component.
|
||||
The component will only write a log message. Keep in mind for later that you have several options for the severity:
|
||||
|
||||
- `_LOGGER.info(msg)`
|
||||
- `_LOGGER.warning(msg)`
|
||||
- `_LOGGER.error(msg)`
|
||||
- `_LOGGER.critical(msg)`
|
||||
- `_LOGGER.exception(msg)`
|
||||
|
||||
7. We return `True` if everything is ok.
|
||||
|
||||
Add the component to your `configuration.yaml` file.
|
||||
|
||||
```yaml
|
||||
hello_state:
|
||||
```
|
||||
|
||||
After a start or a restart of Home Assistant the component will create an entry in the log.
|
||||
|
||||
```bash
|
||||
16-03-12 14:16:42 INFO (MainThread) [custom_components.hello_state] The 'hello state' component is ready!
|
||||
```
|
||||
|
||||
The next step is the introduction of configuration options. A user can pass configuration options to our component via `configuration.yaml`. To use them we'll use the passed in `config` variable to our `setup` method.
|
||||
|
||||
```python
|
||||
import logging
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
DOMAIN = 'hello_state'
|
||||
DEPENDENCIES = []
|
||||
|
||||
CONF_TEXT = 'text'
|
||||
DEFAULT_TEXT = 'No text!'
|
||||
|
||||
def setup(hass, config):
|
||||
"""Set up the Hello State component. """
|
||||
# Get the text from the configuration. Use DEFAULT_TEXT if no name is provided.
|
||||
text = config[DOMAIN].get(CONF_TEXT, DEFAULT_TEXT)
|
||||
|
||||
# States are in the format DOMAIN.OBJECT_ID
|
||||
hass.states.set('hello_state.Hello_State', text)
|
||||
|
||||
return True
|
||||
```
|
||||
|
||||
To use the latest feature of our component, update the entry in your `configuration.yaml` file.
|
||||
|
||||
```yaml
|
||||
hello_state:
|
||||
text: 'Hello, World!'
|
||||
```
|
||||
|
||||
Thanks to `DEFAULT_TEXT` variable the component will launch even if no `text:` field is used in the `configuration.yaml` file. Quite often there are variables which are required. It's important to check if all mandatory configuration variables are provided. If not, the setup should fail. We will use `voluptuous` as a helper to achieve this. The next listing shows the essential parts.
|
||||
|
||||
```python
|
||||
import voluptuous as vol
|
||||
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
CONFIG_SCHEMA = vol.Schema({
|
||||
DOMAIN: vol.Schema({
|
||||
vol.Required(CONF_TEXT): cv.string,
|
||||
})
|
||||
}, extra=vol.ALLOW_EXTRA)
|
||||
```
|
||||
|
||||
Now, when `text:` is missing from the config, Home Assistant will alert the user and not setup your component.
|
||||
|
||||
After a start or a restart of Home Assistant the component will be visible in the frontend if the `configuration.yaml` file is up-to-date.
|
||||
|
||||
<p class='img'>
|
||||
<img src='/img/en/development/create-component01.png' />
|
||||
</p>
|
||||
|
||||
In order to expose attributes for a platform, you will need to define a property called `device_state_attributes` on the entity class, which will return a dictionary of attributes:
|
||||
|
||||
```
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
"""Return device specific state attributes."""
|
||||
return self._attributes
|
||||
```
|
||||
|
||||
> Entities also have a similar property `state_attributes`, which normally doesn't need to be defined by new platforms. This property is used by base components to add standard sets of attributes to a state. Example: The light component uses `state_attributes` to add brightness to the state dictionary. If you are designing a new component, you should define `state_attributes` instead.
|
||||
|
||||
To get your component included in the Home Assistant releases, follow the steps described in the [Submit your work](development_submitting.md) section. Basically you only need to move your component in the `homeassistant/component/` directory of your fork and create a Pull Request.
|
@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Catching up with Reality
|
||||
id: version-0.72-development_catching_up
|
||||
original_id: development_catching_up
|
||||
---
|
||||
|
||||
If it's taking a while to develop your feature, and you want to catch up with what's in the current Home Assistant `dev` branch, you can use `git rebase`. This will pull the latest Home Assistant changes locally, rewind your commits, bring in the latest changes from Home Assistant, and replay all of your commits on top.
|
||||
|
||||
```bash
|
||||
# Run this from your feature branch
|
||||
$ git fetch upstream dev # to pull the latest changes into a local dev branch
|
||||
$ git rebase upstream/dev # to put those changes into your feature branch before your changes
|
||||
```
|
||||
|
||||
If rebase detects conflicts, repeat this process until all changes have been resolved:
|
||||
|
||||
1. `git status` shows you the file with the conflict; edit the file and resolve the lines between `<<<< | >>>>`
|
||||
3. Add the modified file: `git add <file>` or `git add .`
|
||||
4. Continue rebase: `git rebase --continue`
|
||||
5. Repeat until you've resolved all conflicts
|
||||
|
||||
After rebasing your branch, you will have rewritten history relative to your GitHub fork's branch. When you go to push you will see an error that your history has diverged from the original branch. In order to get your GitHub fork up-to-date with your local branch, you will need to force push, using the following command:
|
||||
|
||||
```bash
|
||||
# Run this from your feature branch
|
||||
$ git push origin --force
|
||||
```
|
||||
|
||||
Other workflows are covered in detail in the [Github documentation](https://help.github.com/articles/fork-a-repo/). Add an additional `remote` after you clone your fork.
|
||||
|
||||
```bash
|
||||
$ git remote add upstream https://github.com/home-assistant/home-assistant.git
|
||||
```
|
||||
|
||||
Then, `git pull --rebase upstream dev`.
|
||||
|
15
website/versioned_docs/version-0.72/development_checklist.md
Normal file
15
website/versioned_docs/version-0.72/development_checklist.md
Normal file
@ -0,0 +1,15 @@
|
||||
---
|
||||
title: Development Checklist
|
||||
id: version-0.72-development_checklist
|
||||
original_id: development_checklist
|
||||
---
|
||||
|
||||
|
||||
Before you commit any changes, check your work against these requirements:
|
||||
|
||||
- All dependencies from [pypi](https://pypi.python.org/pypi) are included via the `REQUIREMENTS` variable in your platform or component and only imported inside functions that use them
|
||||
- New dependencies are added to `requirements_all.txt` (if applicable), using `script/gen_requirements_all.py`
|
||||
- The `.coveragerc` file is updated to exclude your platform if there are no tests available or your new code uses a third-party library for communication with the device, service, or sensor
|
||||
- Documentation is developed for [home-assistant.io](/)
|
||||
* It's OK to start with adding a docstring with configuration details (for example, sample entry for `configuration.yaml` file) to the file header. Visit the [website documentation](https://www.home-assistant.io/developers/documentation/) for more information about contributing to [home-assistant.io](https://github.com/home-assistant/home-assistant.github.io).
|
||||
|
104
website/versioned_docs/version-0.72/development_environment.md
Normal file
104
website/versioned_docs/version-0.72/development_environment.md
Normal file
@ -0,0 +1,104 @@
|
||||
---
|
||||
title: Set up Development Environment
|
||||
id: version-0.72-development_environment
|
||||
original_id: development_environment
|
||||
---
|
||||
|
||||
You'll need to set up a development environment if you want to develop a new feature or component for Home Assistant. Read on to learn how to set up.
|
||||
|
||||
## Preparing your environment
|
||||
|
||||
### Developing on Linux
|
||||
|
||||
Install the core dependencies.
|
||||
|
||||
```bash
|
||||
$ sudo apt-get install python3-pip python3-dev python3-venv
|
||||
```
|
||||
|
||||
In order to run `script/setup` below you will need some more dependencies.
|
||||
|
||||
```bash
|
||||
$ sudo apt-get install libssl-dev libxml2-dev libxslt1-dev libjpeg-dev libffi-dev libudev-dev zlib1g-dev
|
||||
```
|
||||
|
||||
> Different distributions have different package installation mechanisms and sometimes packages names as well. For example Centos would use: `sudo yum install epel-release && sudo yum install python36 python36-devel mysql-devel gcc`
|
||||
|
||||
Additional dependencies exist if you plan to perform Frontend Development, please read the [Frontend](frontend_index.md) section to learn more.
|
||||
|
||||
### Developing on Windows
|
||||
|
||||
If you are using Windows as a development platform, make sure that you have the correct Microsoft [Visual C++ build tools](http://landinghub.visualstudio.com/visual-cpp-build-tools) installed. The installation of the most requirements and validation using `tox` will fail if this is not done correctly. Check the [Windows Compilers](https://wiki.python.org/moin/WindowsCompilers) section on the [Python website](https://www.python.org/) for details.
|
||||
|
||||
Due to Home Assistant is mainly designed and developed on Linux distributions it is not recommended to develop on Windows machines. However on Windows 10 machines you should decide to set up a [Linux subsystem](https://docs.microsoft.com/de-de/windows/wsl/install-win10).
|
||||
|
||||
Setup Linux subsystem.
|
||||
|
||||
```bash
|
||||
$ apt-get update
|
||||
$ apt-get upgrade
|
||||
$ echo 'export DISPLAY=:0' >> ~/.bashrc && . ~/.bashrc
|
||||
$ sudo apt-get install xubuntu-desktop -y
|
||||
```
|
||||
|
||||
It is recommended using [PyCharm](https://www.jetbrains.com/pycharm/download/) as debugger. Download and start PyCharm.
|
||||
|
||||
```bash
|
||||
$ wget https://download.jetbrains.com/python/pycharm-community-20XX.X.tar.gz
|
||||
$ tar -xzf pycharm-community-20XX.X
|
||||
$ ./pycharm.sh
|
||||
```
|
||||
|
||||
In order to display the PyCharm GUI on Windows you need to run a X-Server like [VcXserv](https://sourceforge.net/projects/vcxsrv/).
|
||||
|
||||
Also, make sure to install or upgrade the `setuptools` Python package. It contains compatibility improvements and adds automatic use of compilers:
|
||||
|
||||
```bash
|
||||
$ pip install --upgrade setuptools
|
||||
```
|
||||
|
||||
### Developing on OS X
|
||||
|
||||
Install [Homebrew](https://brew.sh/), then use that to install Python 3:
|
||||
|
||||
```bash
|
||||
$ brew install python3
|
||||
```
|
||||
|
||||
## Setup Local Repository
|
||||
|
||||
Visit the [Home Assistant repository](https://github.com/home-assistant/home-assistant) and click **Fork**.
|
||||
Once forked, setup your local copy of the source using the commands:
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/YOUR_GIT_USERNAME/home-assistant.git
|
||||
$ cd home-assistant
|
||||
$ git remote add upstream https://github.com/home-assistant/home-assistant.git
|
||||
```
|
||||
|
||||
## Setting up virtual environment
|
||||
|
||||
To isolate your environment from the rest of the system, set up a [`venv`](https://docs.python.org/3/library/venv.html). Within the `home-assistant` directory, create and activate your virtual environment.
|
||||
|
||||
```bash
|
||||
$ python3 -m venv .
|
||||
$ source bin/activate
|
||||
```
|
||||
|
||||
Install the requirements with a provided script named `setup`.
|
||||
|
||||
```bash
|
||||
$ script/setup
|
||||
```
|
||||
|
||||
Invoke your installation.
|
||||
|
||||
```bash
|
||||
$ hass
|
||||
```
|
||||
|
||||
## Logging
|
||||
|
||||
By default logging in home-assistant is tuned for operating in production (set to INFO by default, with some modules set to even less verbose logging levels).
|
||||
|
||||
You can use the [logger](https://www.home-assistant.io/components/logger/) component to adjust logging to DEBUG to see even more details about what is going on.
|
@ -0,0 +1,76 @@
|
||||
---
|
||||
title: Style guidelines
|
||||
id: version-0.72-development_guidelines
|
||||
original_id: development_guidelines
|
||||
---
|
||||
|
||||
Home Assistant enforces strict [PEP8 style](https://www.python.org/dev/peps/pep-0008/) and [PEP 257 (Docstring Conventions)](https://www.python.org/dev/peps/pep-0257/) compliance on all code submitted. We automatically test every pull request as part of the linting process with [Coveralls](https://coveralls.io/github/home-assistant/home-assistant) and [Travis CI](https://travis-ci.org/home-assistant/home-assistant).
|
||||
|
||||
Summary of the most relevant points:
|
||||
|
||||
- Line length is limited to 79 characters (see below).
|
||||
- Use 4 spaces per indentation level. We don't use tabs.
|
||||
- Comments should be full sentences and end with a period.
|
||||
- [Imports](https://www.python.org/dev/peps/pep-0008/#imports) should be ordered.
|
||||
- Constants and the content of lists and dictionaries should be in alphabetical order.
|
||||
- Avoid trailing whitespace but surround binary operators with a single space.
|
||||
- Line separator should be set to `LF`.
|
||||
|
||||
The maximum line length comes directly from the [PEP8 style guide](https://www.python.org/dev/peps/pep-0008/#maximum-line-length), and is also used by the Python standard library. All code must pass these linting checks, and no exceptions will be made. There have already been numerous requests to increase the maximum line length, but after evaluating the options, the Home Assistant maintainers have decided to stay at 79 characters. This decision is final.
|
||||
|
||||
Those points may require that you adjust your IDE or editor settings.
|
||||
|
||||
## Our recommendations
|
||||
|
||||
For some cases [PEPs](https://www.python.org/dev/peps/) don't make a statement. This section covers our recommendations about the code style. Those points were collected from the existing code and based on what contributors and developers were using the most. This is basically a majority decision, thus you may not agree with it. But we would like to encourage you follow those recommendations to keep the code unified.
|
||||
|
||||
### Quotes
|
||||
|
||||
Use single quotes `'` for single word and `"` for multiple words or sentences.
|
||||
|
||||
```python
|
||||
ATTR_WATERLEVEL = 'level'
|
||||
CONF_ATTRIBUTION = "Data provided by the WUnderground weather service"
|
||||
SENSOR_TYPES = {
|
||||
'alerts': ['Alerts', None],
|
||||
}
|
||||
```
|
||||
|
||||
### File headers
|
||||
|
||||
The docstring in the file header should contain a link to the documentation to make it easy to find further information, especially about the configuration or details which are not mentioned in the code.
|
||||
|
||||
```python
|
||||
"""
|
||||
Support for MQTT lights.
|
||||
|
||||
For more details about this platform, please refer to the documentation at
|
||||
https://home-assistant.io/components/light.mqtt/
|
||||
"""
|
||||
```
|
||||
|
||||
### Requirements
|
||||
|
||||
Please place [Platform requirements](creating_platform_code_review.md#1-requirements) right after the imports.
|
||||
|
||||
```python
|
||||
[...]
|
||||
from homeassistant.helpers.entity import Entity
|
||||
|
||||
REQUIREMENTS = ['xmltodict==0.11.0']
|
||||
```
|
||||
|
||||
### Log messages
|
||||
|
||||
There is no need to add the platform or component name to the log messages. This will be added automatically. Like `syslog` messages there shouldn't be any period at the end. Try to avoid brackets and additional quotes around the output to make it easier for users to parse the log. A widely style is shown below but you are free to compose the messages as you like.
|
||||
|
||||
```python
|
||||
_LOGGER.error("No route to device: %s", self._resource)
|
||||
```
|
||||
|
||||
```bash
|
||||
2017-05-01 14:28:07 ERROR [homeassistant.components.sensor.arest] No route to device: 192.168.0.18
|
||||
```
|
||||
|
||||
Don't print out wrong API keys, tokens, usernames, or passwords.
|
||||
Also note that `_LOGGER.info` is reserved for the core, use `_LOGGER.debug` in anything else.
|
27
website/versioned_docs/version-0.72/development_index.md
Normal file
27
website/versioned_docs/version-0.72/development_index.md
Normal file
@ -0,0 +1,27 @@
|
||||
---
|
||||
title: Starting with Development
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-development_index
|
||||
original_id: development_index
|
||||
---
|
||||
|
||||
Home Assistant is built from the ground up to be easily extensible using components. Home Assistant uses [Python 3](https://www.python.org/) for the backend and [Polymer (Web components)](https://www.polymer-project.org/) for the frontend.
|
||||
|
||||
Home Assistant is open-source and licensed under [Apache 2.0](http://www.apache.org/licenses/LICENSE-2.0). Here are links to the source:
|
||||
|
||||
- [home-assistant](https://github.com/home-assistant/home-assistant): Python server backend.
|
||||
- [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer): Polymer UI.
|
||||
|
||||
For those new to contributing to open source software, make sure you are familiar with all of the tools and concepts used in Home Assistant before you start.
|
||||
|
||||
When contributing Home Assistant code:
|
||||
- [Github](https://guides.github.com/activities/hello-world/)
|
||||
- [Pip and Virtual Environments](https://www.dabapps.com/blog/introduction-to-pip-and-virtualenv-python/)
|
||||
- [Python 3](https://www.python.org/)
|
||||
- [Pylint](https://www.pylint.org)
|
||||
- [Flake8](http://flake8.pycqa.org/en/latest/)
|
||||
- [Tox](http://tox.readthedocs.org/en/latest/)
|
||||
- [TravisCl](https://travis-ci.org/)
|
||||
|
||||
When contributing 3rd Party code to be used by Home Assistant:
|
||||
- [Publishing your own PyPI package](https://jeffknupp.com/blog/2013/08/16/open-sourcing-a-python-project-the-right-way/)
|
@ -0,0 +1,42 @@
|
||||
---
|
||||
title: Submit your work
|
||||
id: version-0.72-development_submitting
|
||||
original_id: development_submitting
|
||||
---
|
||||
|
||||
Submit your improvements, fixes, and new features to Home Assistant one at a time, using GitHub [Pull Requests](https://help.github.com/articles/using-pull-requests). Here are the steps:
|
||||
|
||||
1. From your fork's dev branch, create a new branch to hold your changes:
|
||||
|
||||
`git checkout -b some-feature`
|
||||
|
||||
2. Make your changes, create a [new platform](creating_platform_index.md), develop a [new component](creating_component_index.md), or fix [issues](https://github.com/home-assistant/home-assistant/issues).
|
||||
|
||||
3. [Test your changes](development_testing.md) and check for style violations.
|
||||
|
||||
4. If everything looks good according to these [musts](development_checklist.md), commit your changes:
|
||||
|
||||
`git add .`
|
||||
|
||||
`git commit -m "Added some-feature"`
|
||||
|
||||
* Write a meaningful commit message and not only `Update` or `Fix`.
|
||||
* Use a capital letter to start with your commit message.
|
||||
* Don't prefix your commit message with `[bla.bla]` or `platform:`.
|
||||
* Consider adding tests to ensure that your code works.
|
||||
|
||||
5. Push your committed changes back to your fork on GitHub:
|
||||
|
||||
`git push origin HEAD`
|
||||
|
||||
6. Follow [these steps](https://help.github.com/articles/creating-a-pull-request/) to create your pull request.
|
||||
|
||||
* On GitHub, navigate to the main page of the Home Assistant repository.
|
||||
* In the "Branch" menu, choose the branch that contains your commits (from your fork).
|
||||
* To the right of the Branch menu, click **New pull request**.
|
||||
* Use the base branch dropdown menu to select the branch you'd like to merge your changes into, then use the compare branch drop-down menu to choose the topic branch you made your changes in. Make sure the Home Assistant branch matches with your forked branch (`dev`) else you will propose ALL commits between branches.
|
||||
* Type a title and complete the provided description for your pull request.
|
||||
* Click **Create pull request**.
|
||||
|
||||
7. Check for comments and suggestions on your pull request and keep an eye on the [CI output](https://travis-ci.org/home-assistant/home-assistant/).
|
||||
|
71
website/versioned_docs/version-0.72/development_testing.md
Normal file
71
website/versioned_docs/version-0.72/development_testing.md
Normal file
@ -0,0 +1,71 @@
|
||||
---
|
||||
title: Testing your code
|
||||
id: version-0.72-development_testing
|
||||
original_id: development_testing
|
||||
---
|
||||
|
||||
As states in the [Style guidelines section](development_guidelines.md) all code is checked to verify all unit tests pass and that the code passes the linting tools. Local testing is done using Tox, which has been installed as part of running `script/setup`. To start the tests, simply run it:
|
||||
|
||||
```bash
|
||||
$ tox
|
||||
```
|
||||
**Important:** Run `tox` before you create your pull request to avoid annoying fixes.
|
||||
|
||||
Running Tox will run unit tests against the locally available Pythons, as well as validate the code and document style using `pycodestyle`, `pydocstyle` and `pylint`. You can run tests on only one tox target -- just use `-e` to select an environment. For example, `tox -e lint` runs the linters only, and `tox -e py36` runs unit tests only on Python 3.6.
|
||||
|
||||
Tox uses virtual environments under the hood to create isolated testing environments. The tox virtual environments will get out-of-date when requirements change, causing test errors. Run `tox -r` to tell Tox to recreate the virtual environments.
|
||||
|
||||
If you are working on tests for a component or platform and you need the dependencies available inside the Tox environment, update the list inside `script/gen_requirements_all.py`. Then run the script and then run `tox -r` to recreate the virtual environments.
|
||||
|
||||
### Running single tests using Tox
|
||||
|
||||
You can pass arguments via Tox to py.test to be able to run single test suites or test files. Replace `py36` with the Python version that you use.
|
||||
|
||||
```bash
|
||||
# Stop after the first test fails
|
||||
$ tox -e py36 -- tests/test_core.py -x
|
||||
# Run test with specified name
|
||||
$ tox -e py36 -- tests/test_core.py -k test_split_entity_id
|
||||
# Fail a test after it runs for 2 seconds
|
||||
$ tox -e py36 -- tests/test_core.py --timeout 2
|
||||
# Show the 10 slowest tests
|
||||
$ tox -e py36 -- tests/test_core.py --duration=10
|
||||
```
|
||||
|
||||
### Testing outside of Tox
|
||||
|
||||
Running tox will invoke the full test suite. Even if you specify which tox target to run, you still run all tests inside that target. That's not very convenient to quickly iterate on your code! To be able to run the specific test suites without Tox, you'll need to install the test dependencies into your Python environment:
|
||||
|
||||
```bash
|
||||
$ pip3 install -r requirements_test_all.txt
|
||||
```
|
||||
|
||||
Now that you have all test dependencies installed, you can run tests on individual files:
|
||||
|
||||
```bash
|
||||
$ flake8 homeassistant/core.py
|
||||
$ pylint homeassistant/core.py
|
||||
$ pydocstyle homeassistant/core.py
|
||||
$ py.test tests/test_core.py
|
||||
```
|
||||
|
||||
You can also run linting tests against all changed files, as reported by `git diff upstream/dev... --diff-filter=d --name-only`, using the `lint` script:
|
||||
|
||||
```bash
|
||||
$ script/lint
|
||||
```
|
||||
|
||||
### Preventing Linter Errors
|
||||
|
||||
Save yourself the hassle of extra commits just to fix style errors by enabling the Flake8 git commit hook. Flake8 will check your code when you try to commit to the repository and block the commit if there are any style errors, which gives you a chance to fix them!
|
||||
|
||||
```bash
|
||||
$ pip3 install flake8 flake8-docstrings
|
||||
$ flake8 --install-hook=git
|
||||
```
|
||||
|
||||
The `flake8-docstrings` extension will check docstrings according to [PEP257](https://www.python.org/dev/peps/pep-0257/) when running Flake8.
|
||||
|
||||
### Notes on PyLint and PEP8 validation
|
||||
|
||||
If you can't avoid a PyLint warning, add a comment to disable the PyLint check for that line with `# pylint: disable=YOUR-ERROR-NAME`. Example of an unavoidable one is if PyLint incorrectly reports that a certain object doesn't have a certain member.
|
25
website/versioned_docs/version-0.72/development_typing.md
Normal file
25
website/versioned_docs/version-0.72/development_typing.md
Normal file
@ -0,0 +1,25 @@
|
||||
---
|
||||
title: Adding type hints to your code
|
||||
id: version-0.72-development_typing
|
||||
original_id: development_typing
|
||||
---
|
||||
|
||||
Type hints in Python are static annotations of variables and functions, to let humans more easily understand the code. See the standard library [docs](https://docs.python.org/3/library/typing.html) and this PyCascades 2018 [talk](https://youtu.be/zKre4DKAB30).
|
||||
|
||||
Type hints are not required for all modules at the moment in Home Assistant, but we aim to have complete coverage of the core modules.
|
||||
|
||||
Adding type hints to an existing codebase can be a daunting task. To speed this up and help developers doing this, Instagram made the [`monkeytype`](https://pypi.org/project/MonkeyType/) program. It will analyze calls during runtime and try to assign the correct type hints to the code.
|
||||
|
||||
See [this instagram blog post](https://instagram-engineering.com/let-your-code-type-hint-itself-introducing-open-source-monkeytype-a855c7284881) for a description of the workflow involved to use the monkeytype program.
|
||||
|
||||
We've added a script to start a run of our test suite or a test module and tell the `monkeytype` program to analyze the run.
|
||||
|
||||
### Basic workflow
|
||||
1. Run `script/monkeytype tests/path/to/your_test_module.py`.
|
||||
2. Run `monkeytype stub homeassistant.your_actual_module`.
|
||||
3. Look at output from the monkeytyped typing stub. If not totally bad, apply the stub to your module. You most likely will need to manually edit the typing in the last step.
|
||||
4. Run `monkeytype apply homeassistant.your_actual_module`.
|
||||
5. Check the diff and manually correct the typing if needed. Commit, push the branch and make a PR.
|
||||
|
||||
**Note:**
|
||||
Applying a monkeytyped stub to a module that has existing typing annotations might error and not work. This tool is most useful for totally untyped modules.
|
@ -0,0 +1,82 @@
|
||||
---
|
||||
title: Validate the input
|
||||
id: version-0.72-development_validation
|
||||
original_id: development_validation
|
||||
---
|
||||
|
||||
The `configuration.yaml` file contains the configuration options for components and platforms. We use [voluptuous](https://pypi.python.org/pypi/voluptuous) to make sure that the configuration provided by the user is valid. Some entries are optional or could be required to set up a platform or a component. Others must be a defined type or from an already-defined list.
|
||||
|
||||
We test the configuration to ensure that users have a great experience and minimize notifications if something is wrong with a platform or component setup before Home Assistant runs.
|
||||
|
||||
Besides [voluptuous](https://pypi.python.org/pypi/voluptuous) default types, many custom types are available. For an overview, take a look at the [config_validation.py](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/helpers/config_validation.py) helper.
|
||||
|
||||
- Types: `string`, `byte`, and `boolean`
|
||||
- Entity ID: `entity_id` and `entity_ids`
|
||||
- Numbers: `small_float` and `positive_int`
|
||||
- Time: `time`, `time_zone`
|
||||
- Misc: `template`, `slug`, `temperature_unit`, `latitude`, `longitude`, `isfile`, `sun_event`, `ensure_list`, `port`, `url`, and `icon`
|
||||
|
||||
To validate platforms using [MQTT](https://www.home-assistant.io/components/mqtt/), `valid_subscribe_topic` and `valid_publish_topic` are available.
|
||||
|
||||
Some things to keep in mind:
|
||||
|
||||
- Use the constants defined in `const.py`
|
||||
- Import `PLATFORM_SCHEMA` from the parent component and extend it
|
||||
- Preferred order is `required` first and `optional` second
|
||||
- Starting with Home Assistant 0.64 `voluptuous` requires default values for optional configuration keys to be valid values. Don't use a default which is `None` like `vol.Optional(CONF_SOMETHING, default=None): cv.string`, set the default to `default=""` if required.
|
||||
|
||||
### Snippets
|
||||
|
||||
This section contains snippets for the validation we use.
|
||||
|
||||
#### Default name
|
||||
|
||||
It's common to set a default for a sensor if the user doesn't provide a name to use.
|
||||
|
||||
```python
|
||||
DEFAULT_NAME = 'Sensor name'
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
...
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
```
|
||||
|
||||
#### Limit the values
|
||||
|
||||
You might want to limit the user's input to a couple of options.
|
||||
|
||||
```python
|
||||
DEFAULT_METHOD = 'GET'
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
...
|
||||
vol.Optional(CONF_METHOD, default=DEFAULT_METHOD): vol.In(['POST', 'GET']),
|
||||
```
|
||||
|
||||
#### Port
|
||||
|
||||
All port numbers are from a range of 1 to 65535.
|
||||
|
||||
```python
|
||||
DEFAULT_PORT = 993
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
...
|
||||
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
|
||||
```
|
||||
|
||||
#### Lists
|
||||
|
||||
If a sensor has a pre-defined list of available options, test to make sure the configuration entry matches the list.
|
||||
|
||||
```python
|
||||
SENSOR_TYPES = {
|
||||
'article_cache': ('Article Cache', 'MB'),
|
||||
'average_download_rate': ('Average Speed', 'MB/s'),
|
||||
}
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||
...
|
||||
vol.Optional(CONF_MONITORED_VARIABLES, default=[]):
|
||||
vol.All(cv.ensure_list, [vol.In(SENSOR_TYPES)]),
|
||||
```
|
@ -0,0 +1,27 @@
|
||||
---
|
||||
title: Alarm Control Panel Entity
|
||||
sidebar_label: Alarm Control Panel
|
||||
id: version-0.72-entity_alarm_control_panel
|
||||
original_id: entity_alarm_control_panel
|
||||
---
|
||||
|
||||
> This entry is incomplete. Contribution welcome.
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| code_format | string | `None` | The format of the panel code.
|
||||
|
||||
### Available code formats
|
||||
|
||||
| Value | Description
|
||||
| ----- | -----------
|
||||
| None | No code required.
|
||||
| Number | Code is a number (Shows ten-key pad on frontend).
|
||||
| Any | Code is a string.
|
||||
|
||||
## Methods
|
||||
|
45
website/versioned_docs/version-0.72/entity_binary_sensor.md
Normal file
45
website/versioned_docs/version-0.72/entity_binary_sensor.md
Normal file
@ -0,0 +1,45 @@
|
||||
---
|
||||
title: Binary Sensor Entity
|
||||
sidebar_label: Binary Sensor
|
||||
id: version-0.72-entity_binary_sensor
|
||||
original_id: entity_binary_sensor
|
||||
---
|
||||
|
||||
A binary sensor is a sensor that can only have two states.
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| is_on| boolean | **Required** | If the binary sensor is currently on or off.
|
||||
| device_class | string | `None` | Type of binary sensor.
|
||||
|
||||
### Available device classes
|
||||
|
||||
| Value | Description
|
||||
| ----- | -----------
|
||||
| battery | On means low, Off means normal.
|
||||
| cold | On means cold, Off means normal.
|
||||
| connectivity | On means connected, Off means disconnected.
|
||||
| door | On means open, Off means closed.
|
||||
| garage_door | On means open, Off means closed.
|
||||
| gas | On means gas detected, Off means no gas (clear).
|
||||
| heat | On means hot, Off means normal.
|
||||
| light | On means light detected, Off means no light.
|
||||
| lock | On means open (unlocked), Off means closed (locked).
|
||||
| moisture | On means wet, Off means dry.
|
||||
| motion | On means motion detected, Off means no motion (clear).
|
||||
| moving | On means moving, Off means not moving (stopped).
|
||||
| occupancy | On means occupied, Off means not occupied (clear).
|
||||
| opening | On means open, Off means closed.
|
||||
| plug | On means plugged in, Off means unplugged.
|
||||
| power | On means power detected, Off means no power.
|
||||
| presence | On means home, Off means away.
|
||||
| problem | On means problem detected, Off means no problem (OK).
|
||||
| safety | On means unsafe, Off means safe.
|
||||
| smoke | On means smoke detected, Off means no smoke (clear).
|
||||
| sound | On means sound detected, Off means no sound (clear).
|
||||
| vibration | On means vibration detected, Off means no vibration.
|
||||
| window | On means open, Off means closed.
|
18
website/versioned_docs/version-0.72/entity_climate.md
Normal file
18
website/versioned_docs/version-0.72/entity_climate.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Climate Entity
|
||||
sidebar_label: Climate
|
||||
id: version-0.72-entity_climate
|
||||
original_id: entity_climate
|
||||
---
|
||||
|
||||
> This entry is incomplete. Contribution welcome.
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
|
||||
## Methods
|
||||
|
18
website/versioned_docs/version-0.72/entity_cover.md
Normal file
18
website/versioned_docs/version-0.72/entity_cover.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Cover Entity
|
||||
sidebar_label: Cover
|
||||
id: version-0.72-entity_cover
|
||||
original_id: entity_cover
|
||||
---
|
||||
|
||||
> This entry is incomplete. Contribution welcome.
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
|
||||
## Methods
|
||||
|
18
website/versioned_docs/version-0.72/entity_fan.md
Normal file
18
website/versioned_docs/version-0.72/entity_fan.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Fan Entity
|
||||
sidebar_label: Fan
|
||||
id: version-0.72-entity_fan
|
||||
original_id: entity_fan
|
||||
---
|
||||
|
||||
> This entry is incomplete. Contribution welcome.
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
|
||||
## Methods
|
||||
|
104
website/versioned_docs/version-0.72/entity_index.md
Normal file
104
website/versioned_docs/version-0.72/entity_index.md
Normal file
@ -0,0 +1,104 @@
|
||||
---
|
||||
title: Entity
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-entity_index
|
||||
original_id: entity_index
|
||||
---
|
||||
|
||||
Each device is represented in Home Assistant as an entity. An entity abstracts away the internal working of Home Assistant. As an integrator you don't have to worry about how services or the state machine work. Instead, you extend an entity class and implement the necessary properties and methods for the device type that you're integrating.
|
||||
|
||||
Below is an example switch entity that keeps track of their state in memory.
|
||||
|
||||
```python
|
||||
from homeassistant.components.switch import SwitchDevice
|
||||
|
||||
class MySwitch(SwitchDevice):
|
||||
|
||||
def __init__(self):
|
||||
self._is_on = False
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Name of the device."""
|
||||
return 'My Switch'
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""If the switch is currently on or off."""
|
||||
return self._is_on
|
||||
|
||||
def turn_on(self, **kwargs):
|
||||
"""Turn the switch on."""
|
||||
self._is_on = True
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Turn the switch off."""
|
||||
self._is_on = False
|
||||
```
|
||||
|
||||
That's all there is to it to build a switch entity! Continue reading to learn more or check out the [video tutorial](https://youtu.be/Cfasc9EgbMU?t=737).
|
||||
|
||||
## Updating the entity
|
||||
|
||||
An entity represents a device. There are various strategies to keep your entity in sync with the state of the device, the most popular one being polling.
|
||||
|
||||
### Polling
|
||||
|
||||
With polling, Home Assistant will ask the entity from time to time (depending on the update interval of the component) to fetch the latest state. Home Assistant will poll an entity when the `should_poll` property returns `True` (the default value). You can either implement your update logic using `update()` or the async method `async_update()`. This method should fetch the latest state from the device and store it in an instance variable for the properties to return it.
|
||||
|
||||
### Subscribing to updates
|
||||
|
||||
When you subscribe to updates, your code is responsible for letting Home Assistant know that an update is available. Make sure you have the `should_poll` property return `False`.
|
||||
|
||||
Whenever you receive new state from your subscription, you can tell Home Assistant that an update is available by calling `schedule_update_ha_state()` or async callback `async_schedule_update_ha_state()`. Pass in the boolean `True` to the method if you want Home Assistant to call your update method before writing the update to Home Assistant.
|
||||
|
||||
## Generic properties
|
||||
|
||||
The entity base class has a few properties that are common among all entities in Home Assistant. These can be added to any entity regardless of the type. All these properties are optional and don't need to be implemented.
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| assumed_state | boolean | `False` | Return `True` if the state is based on our assumption instead of reading it from the device.
|
||||
| available | boolean | `True` | Indiciate if Home Assistant is able to read the state and control the underlying device.
|
||||
| device_state_attributes | dict | `None` | Extra information to store in the state machine. It needs to be information that further explains the state, it should not be static information like firmware version. See [below](entity_index.md#standard_attributes) for details of standard attributes.
|
||||
| entity_picture | URL | `None` | Url of a picture to show for the entity.
|
||||
| name | string | `None` | Name of the entity
|
||||
| should_poll | boolean | `True` | Should Home Assistant check with the entity for an updated state. If set to `False`, entity will need to notify Home Assistant of new updates by calling one of the [schedule update methods](#methods).
|
||||
| unique_id | string | `None` | A unique identifier for this entity. Needs to be unique within a platform (ie `light.hue`). Should not be configurable by the user or be changable. [Learn more.](entity_registry_index.md#unique-id-requirements)
|
||||
|
||||
## Advanced properties
|
||||
|
||||
The following properties are also available on entities. However, they are for advanced use only and should be used with caution.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| force_update | boolean | `False` | Write each update to the state machine, even if the data is the same. Example use: when you are directly reading the value from a connected sensor instead of a cache. Use with caution, will spam the state machine.
|
||||
| hidden | boolean | `False` | Indicate if the entity should not be shown on the frontend.
|
||||
| icon | icon | `None` | Icon to use in the frontend. Icons start with `mdi:` plus an [identifier](https://materialdesignicons.com/). You probably don't need this since Home Assistant already provides default icons for all devices.
|
||||
|
||||
## Standard attributes
|
||||
|
||||
The following `device_state_attributes` are considered standard and should follow the convention below. The constant should be imported from `homeassistant/const.py`.
|
||||
|
||||
| Name | Type | Unit | Constant | Description
|
||||
| ---- | ---- | ---- | -------- | -----------
|
||||
| battery_charging | boolean | N/A | `ATTR_BATTERY_CHARGING` | Battery charging status of the entity, shown as a boolean `true` or `false`. If charging is not supported, then this attribute should not be created.
|
||||
| battery_level | integer | % | `ATTR_BATTERY_LEVEL` | Battery level of the entity, shown as an integer percentage between 0-100.
|
||||
|
||||
## Lifecycle hooks
|
||||
|
||||
Use these lifecycle hooks to execute code when certain events happen to the entity. All lifecycle hooks are async methods.
|
||||
|
||||
### `async_added_to_hass()`
|
||||
|
||||
Called when an entity has their entity_id and hass object assigned, before it is written to the state machine for the first time. Example uses: restore the state or subscribe to updates.
|
||||
|
||||
### `async_will_remove_from_hass()`
|
||||
|
||||
Called when an entity is about to be removed from Home Assistant. Example use: disconnect from the server or unsubscribe from updates.
|
||||
|
||||
## Changing the entity model
|
||||
|
||||
If you want to add a new feature to an entity or any of its subtypes (light, switch, etc), you will need to propose it first in our [architecture repo](https://github.com/home-assistant/architecture/issues). Only additions will be considered that are common features among various vendors.
|
18
website/versioned_docs/version-0.72/entity_light.md
Normal file
18
website/versioned_docs/version-0.72/entity_light.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Light Entity
|
||||
sidebar_label: Light
|
||||
id: version-0.72-entity_light
|
||||
original_id: entity_light
|
||||
---
|
||||
|
||||
> This entry is incomplete. Contribution welcome.
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
|
||||
## Methods
|
||||
|
18
website/versioned_docs/version-0.72/entity_lock.md
Normal file
18
website/versioned_docs/version-0.72/entity_lock.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Lock Entity
|
||||
sidebar_label: Lock
|
||||
id: version-0.72-entity_lock
|
||||
original_id: entity_lock
|
||||
---
|
||||
|
||||
> This entry is incomplete. Contribution welcome.
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
|
||||
## Methods
|
||||
|
31
website/versioned_docs/version-0.72/entity_media_player.md
Normal file
31
website/versioned_docs/version-0.72/entity_media_player.md
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: Media Player Entity
|
||||
sidebar_label: Media Player
|
||||
id: version-0.72-entity_media_player
|
||||
original_id: entity_media_player
|
||||
---
|
||||
|
||||
> This entry is incomplete. Contribution welcome.
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| sound_mode | string | None | The current sound mode of the media player
|
||||
| sound_mode_list | list | None | Dynamic list of available sound modes (set by platform, empty means sound mode not supported)
|
||||
|
||||
|
||||
## Methods
|
||||
### Select sound mode
|
||||
Optional. Switch the sound mode of the media player.
|
||||
|
||||
class MyMediaPlayer(MediaPlayerDevice):
|
||||
# Implement one of these methods.
|
||||
|
||||
def select_sound_mode(self, sound_mode):
|
||||
"""Switch the sound mode of the entity."""
|
||||
|
||||
def async_select_sound_mode(self, sound_mode):
|
||||
"""Switch the sound mode of the entity."""
|
24
website/versioned_docs/version-0.72/entity_registry_index.md
Normal file
24
website/versioned_docs/version-0.72/entity_registry_index.md
Normal file
@ -0,0 +1,24 @@
|
||||
---
|
||||
title: Entity Registry
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-entity_registry_index
|
||||
original_id: entity_registry_index
|
||||
---
|
||||
|
||||
The entity registry is a registry where Home Assistant keeps track of entities. Any entity that is added to Home Assistant and has a unique ID will be registered in the registry.
|
||||
|
||||
Being registered has the advantage that the same entity will always get the same entity ID. It will also prevent other entities from using that entity ID.
|
||||
|
||||
A user is also able to override the name of an entity in the entity registry. When set, the name of the entity registry is used in favor of the name the device might give itself.
|
||||
|
||||
## Unique ID requirements
|
||||
|
||||
An entity is looked up in the registry based on a combination of domain (ie `light`), platform name (ie `hue`) and the unique ID of the entity. It is therefore very important that the unique ID is unique! It is also important that it is not possible for the user to change the unique ID, because that means it will lose all its settings related to it.
|
||||
|
||||
Good sources for a unique ID:
|
||||
|
||||
- Serial number of a device
|
||||
- MAC address of a device
|
||||
- latitude/longitude
|
||||
|
||||
If a device has a single serial but provides multiple entities, combine the serial with unique identifiers for the entities. For example, if a device measures both temperature and humidithy, you can uniqueley identify the entities using `{serial}-{sensor_type}`.
|
18
website/versioned_docs/version-0.72/entity_remote.md
Normal file
18
website/versioned_docs/version-0.72/entity_remote.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Remote Entity
|
||||
sidebar_label: Remote
|
||||
id: version-0.72-entity_remote
|
||||
original_id: entity_remote
|
||||
---
|
||||
|
||||
> This entry is incomplete. Contribution welcome.
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
|
||||
## Methods
|
||||
|
29
website/versioned_docs/version-0.72/entity_sensor.md
Normal file
29
website/versioned_docs/version-0.72/entity_sensor.md
Normal file
@ -0,0 +1,29 @@
|
||||
---
|
||||
title: Sensor Entity
|
||||
sidebar_label: Sensor
|
||||
id: version-0.72-entity_sensor
|
||||
original_id: entity_sensor
|
||||
---
|
||||
|
||||
A sensor is a read-only entity that provides some information. Information has a value and optionally, a unit of measurement.
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| state | string | **Required** | The value of the sensor.
|
||||
| unit_of_measurement | string | `None` | The unit of measurement that the sensor is expressed in.
|
||||
| device_class | string | `None` | Type of sensor.
|
||||
|
||||
### Available device classes
|
||||
|
||||
If specifying a device class, your sensor entity will need to also return the correct unit of measurement.
|
||||
|
||||
| Type | Unit | Description
|
||||
| ---- | ---- | -----------
|
||||
| battery | % | % of battery that is left.
|
||||
| humidity | % | % of humidity in the air.
|
||||
| illuminance | lx/lm | Light level.
|
||||
| temperature | C/F | Temperature.
|
65
website/versioned_docs/version-0.72/entity_switch.md
Normal file
65
website/versioned_docs/version-0.72/entity_switch.md
Normal file
@ -0,0 +1,65 @@
|
||||
---
|
||||
title: Switch Entity
|
||||
sidebar_label: Switch
|
||||
id: version-0.72-entity_switch
|
||||
original_id: entity_switch
|
||||
---
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| is_on | boolean | **Required** | If the switch is currently on or off.
|
||||
| current_power_w | float | `None` | The current power usage in W.
|
||||
| today_energy_kwh | float | `None` | Total energy usage in kWh.
|
||||
| is_standby | boolean | `None` | Indicate if the device connected to the switch is currently in standby.
|
||||
|
||||
## Methods
|
||||
|
||||
### Turn On
|
||||
|
||||
Turn the switch on.
|
||||
|
||||
```python
|
||||
class MySwitch(SwitchDevice):
|
||||
# Implement one of these methods.
|
||||
|
||||
def turn_on(self, **kwargs) -> None:
|
||||
"""Turn the entity on."""
|
||||
|
||||
async def async_turn_on(self, **kwargs):
|
||||
"""Turn the entity on."""
|
||||
|
||||
```
|
||||
|
||||
### Turn Off
|
||||
|
||||
Turn the switch off.
|
||||
|
||||
```python
|
||||
class MySwitch(SwitchDevice):
|
||||
# Implement one of these methods.
|
||||
|
||||
def turn_off(self, **kwargs):
|
||||
"""Turn the entity off."""
|
||||
|
||||
async def async_turn_off(self, **kwargs):
|
||||
"""Turn the entity off."""
|
||||
```
|
||||
|
||||
### Toggle
|
||||
|
||||
Optional. If not implemented will default to checking what method to call using the `is_on` property.
|
||||
|
||||
```python
|
||||
class MySwitch(SwitchDevice):
|
||||
# Implement one of these methods.
|
||||
|
||||
def toggle(self, **kwargs):
|
||||
"""Toggle the entity."""
|
||||
|
||||
async def async_toggle(self, **kwargs):
|
||||
"""Toggle the entity."""
|
||||
```
|
18
website/versioned_docs/version-0.72/entity_vacuum.md
Normal file
18
website/versioned_docs/version-0.72/entity_vacuum.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Vacuum Entity
|
||||
sidebar_label: Vacuum
|
||||
id: version-0.72-entity_vacuum
|
||||
original_id: entity_vacuum
|
||||
---
|
||||
|
||||
> This entry is incomplete. Contribution welcome.
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
|
||||
## Methods
|
||||
|
57
website/versioned_docs/version-0.72/entity_weather.md
Normal file
57
website/versioned_docs/version-0.72/entity_weather.md
Normal file
@ -0,0 +1,57 @@
|
||||
---
|
||||
title: Weather Entity
|
||||
sidebar_label: Weather
|
||||
id: version-0.72-entity_weather
|
||||
original_id: entity_weather
|
||||
---
|
||||
|
||||
## Properties
|
||||
|
||||
> Properties should always only return information from memory and not do I/O (like network requests). Implement `update()` or `async_update()` to fetch data.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| state | string | **Required** | The current weather condition.
|
||||
| temperature | float | **Required** | The current temperature in °C or °F.
|
||||
| pressure | float | `None` | The current air pressure in hPa or inHg.
|
||||
| humidity | float | `None` | The current humidity in %.
|
||||
| visibility | float | `None` | The current visibility in km or mi.
|
||||
| wind_speed | float | `None` | The current wind speed in km/h or mi/h.
|
||||
| wind_bearing | string | `None` | The current wind bearing, 1-3 letters.
|
||||
| forecast | array | `None` | Daily or Hourly forecast data.
|
||||
| attribution | string | `None` | The branding text required by the API provider.
|
||||
|
||||
Properties have to follow the units defined in the `unit_system`.
|
||||
|
||||
### Forecast
|
||||
|
||||
Forecast data should either be daily or hourly.
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| datetime | string | **Required** | UTC Date time in RFC 3339 format.
|
||||
| temperature | float | **Required** | The higher temperature in °C or °F
|
||||
| condition | string | `None` | The weather condition at this point.
|
||||
| templow | float | `None` | The lower daily Temperature in °C or °F
|
||||
|
||||
### Recommended values for state and condition
|
||||
|
||||
These weather conditions are included in our translation files and also show the corresponding icon.
|
||||
|
||||
| Condition | Description
|
||||
| --------- | -----------
|
||||
| clear-night | Clear night
|
||||
| cloudy | Many clouds
|
||||
| fog | Fog
|
||||
| lightning | Lightning/ thunderstorms
|
||||
| lightning-rainy | Lightning/ thunderstorms and rain
|
||||
| partlycloudy | A few clouds
|
||||
| pouring | Pouring rain
|
||||
| rainy | Rain
|
||||
| snowy | Snow
|
||||
| snowy-rainy | Snow and Rain
|
||||
| sunny | Sunshine
|
||||
| windy | Wind
|
||||
| windy-variant | Wind and clouds
|
||||
|
||||
This means that the `weather` platforms don't need to support languages.
|
517
website/versioned_docs/version-0.72/external_api_rest.md
Normal file
517
website/versioned_docs/version-0.72/external_api_rest.md
Normal file
@ -0,0 +1,517 @@
|
||||
---
|
||||
title: REST API
|
||||
id: version-0.72-external_api_rest
|
||||
original_id: external_api_rest
|
||||
---
|
||||
|
||||
Home Assistant runs a web server accessible on port 8123.
|
||||
|
||||
* http://IP_ADDRESS:8123/ is an interface to control Home Assistant.
|
||||
* http://IP_ADDRESS:8123/api/ is a Rest API.
|
||||
|
||||
The API accepts and returns only JSON encoded objects. All API calls have to be accompanied by the header `X-HA-Access: YOUR_PASSWORD` (YOUR_PASSWORD as specified in your `configuration.yaml` file in the [`http:` section](https://www.home-assistant.io/components/http/)).
|
||||
|
||||
If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file.
|
||||
|
||||
There are multiple ways to consume the Home Assistant Rest API. One is with `curl`:
|
||||
|
||||
```bash
|
||||
curl -X GET \
|
||||
-H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" \
|
||||
http://IP_ADDRESS:8123/ENDPOINT
|
||||
```
|
||||
|
||||
Another option is to use Python and the [Requests](http://docs.python-requests.org/en/latest/) module. =
|
||||
|
||||
```python
|
||||
from requests import get
|
||||
|
||||
url = 'http://localhost:8123/ENDPOINT'
|
||||
headers = {'x-ha-access': 'YOUR_PASSWORD',
|
||||
'content-type': 'application/json'}
|
||||
|
||||
response = get(url, headers=headers)
|
||||
print(response.text)
|
||||
```
|
||||
|
||||
> You can append `?api_password=YOUR_PASSWORD` to any URL to log in automatically.
|
||||
|
||||
Successful calls will return status code 200 or 201. Other status codes that can return are:
|
||||
|
||||
- 400 (Bad Request)
|
||||
- 401 (Unauthorized)
|
||||
- 404 (Not Found)
|
||||
- 405 (Method not allowed)
|
||||
|
||||
### Actions
|
||||
|
||||
The API supports the following actions:
|
||||
|
||||
#### GET /api/
|
||||
|
||||
Returns a message if the API is up and running.
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "API running."
|
||||
}
|
||||
```
|
||||
|
||||
Sample `curl` command:
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" http://localhost:8123/api/
|
||||
```
|
||||
|
||||
#### GET /api/config
|
||||
|
||||
Returns the current configuration as JSON.
|
||||
|
||||
```json
|
||||
{
|
||||
"components":[
|
||||
"sensor.cpuspeed",
|
||||
"frontend",
|
||||
"config.core",
|
||||
"http",
|
||||
"map",
|
||||
"api",
|
||||
"sun",
|
||||
"config",
|
||||
"discovery",
|
||||
"conversation",
|
||||
"recorder",
|
||||
"group",
|
||||
"sensor",
|
||||
"websocket_api",
|
||||
"automation",
|
||||
"config.automation",
|
||||
"config.customize"
|
||||
],
|
||||
"config_dir":"/home/ha/.homeassistant",
|
||||
"elevation":510,
|
||||
"latitude":45.8781529,
|
||||
"location_name":"Home",
|
||||
"longitude":8.458853651,
|
||||
"time_zone":"Europe/Zurich",
|
||||
"unit_system":{
|
||||
"length":"km",
|
||||
"mass":"g",
|
||||
"temperature":"\u00b0C",
|
||||
"volume":"L"
|
||||
},
|
||||
"version":"0.56.2",
|
||||
"whitelist_external_dirs":[
|
||||
"/home/ha/.homeassistant/www",
|
||||
"/home/ha/.homeassistant/"
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Sample `curl` command:
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" http://localhost:8123/api/config
|
||||
```
|
||||
|
||||
#### GET /api/discovery_info
|
||||
|
||||
Returns basic information about the Home Assistant instance as JSON.
|
||||
|
||||
```json
|
||||
{
|
||||
"base_url": "http://192.168.0.2:8123",
|
||||
"location_name": "Home",
|
||||
"requires_api_password": true,
|
||||
"version": "0.56.2"
|
||||
}
|
||||
```
|
||||
|
||||
Sample `curl` command:
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" http://localhost:8123/api/discovery_info
|
||||
```
|
||||
|
||||
#### GET /api/events
|
||||
|
||||
Returns an array of event objects. Each event object contains event name and listener count.
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"event": "state_changed",
|
||||
"listener_count": 5
|
||||
},
|
||||
{
|
||||
"event": "time_changed",
|
||||
"listener_count": 2
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Sample `curl` command:
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" http://localhost:8123/api/events
|
||||
```
|
||||
|
||||
#### GET /api/services
|
||||
|
||||
Returns an array of service objects. Each object contains the domain and which services it contains.
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"domain": "browser",
|
||||
"services": [
|
||||
"browse_url"
|
||||
]
|
||||
},
|
||||
{
|
||||
"domain": "keyboard",
|
||||
"services": [
|
||||
"volume_up",
|
||||
"volume_down"
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Sample `curl` command:
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" http://localhost:8123/api/services
|
||||
```
|
||||
|
||||
#### GET /api/history/period/<timestamp>
|
||||
|
||||
Returns an array of state changes in the past. Each object contains further details for the entities.
|
||||
|
||||
The `<timestamp>` (`YYYY-MM-DDThh:mm:ssTZD`) is optional and defaults to 1 day before the time of the request. It determines the beginning of the period.
|
||||
|
||||
You can pass the following optional GET parameters:
|
||||
|
||||
- `filter_entity_id=<entity_id>` to filter on a single entity
|
||||
- `end_time=<timestamp>` to choose the end of the period in URL encoded format (defaults to 1 day).
|
||||
|
||||
```json
|
||||
[
|
||||
[
|
||||
{
|
||||
"attributes": {
|
||||
"friendly_name": "Weather Temperature",
|
||||
"unit_of_measurement": "\u00b0C"
|
||||
},
|
||||
"entity_id": "sensor.weather_temperature",
|
||||
"last_changed": "2016-02-06T22:15:00+00:00",
|
||||
"last_updated": "2016-02-06T22:15:00+00:00",
|
||||
"state": "-3.9"
|
||||
},
|
||||
{
|
||||
"attributes": {
|
||||
"friendly_name": "Weather Temperature",
|
||||
"unit_of_measurement": "\u00b0C"
|
||||
},
|
||||
"entity_id": "sensor.weather_temperature",
|
||||
"last_changed": "2016-02-06T22:15:00+00:00",
|
||||
"last_updated": "2016-02-06T22:15:00+00:00",
|
||||
"state": "-1.9"
|
||||
},
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
Sample `curl` commands:
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" \
|
||||
http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00
|
||||
```
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" \
|
||||
http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?filter_entity_id=sensor.temperature
|
||||
```
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" \
|
||||
http://localhost:8123/api/history/period/2016-12-29T00:00:00+02:00?end_time=2016-12-31T00%3A00%3A00%2B02%3A00
|
||||
```
|
||||
|
||||
#### GET /api/states
|
||||
|
||||
Returns an array of state objects. Each state has the following attributes: entity_id, state, last_changed and attributes.
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"attributes": {},
|
||||
"entity_id": "sun.sun",
|
||||
"last_changed": "2016-05-30T21:43:32.418320+00:00",
|
||||
"state": "below_horizon"
|
||||
},
|
||||
{
|
||||
"attributes": {},
|
||||
"entity_id": "process.Dropbox",
|
||||
"last_changed": "22016-05-30T21:43:32.418320+00:00",
|
||||
"state": "on"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Sample `curl` command:
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" http://localhost:8123/api/states
|
||||
```
|
||||
|
||||
#### GET /api/states/<entity_id>
|
||||
|
||||
Returns a state object for specified entity_id. Returns 404 if not found.
|
||||
|
||||
```json
|
||||
{
|
||||
"attributes":{
|
||||
"azimuth":336.34,
|
||||
"elevation":-17.67,
|
||||
"friendly_name":"Sun",
|
||||
"next_rising":"2016-05-31T03:39:14+00:00",
|
||||
"next_setting":"2016-05-31T19:16:42+00:00"
|
||||
},
|
||||
"entity_id":"sun.sun",
|
||||
"last_changed":"2016-05-30T21:43:29.204838+00:00",
|
||||
"last_updated":"2016-05-30T21:50:30.529465+00:00",
|
||||
"state":"below_horizon"
|
||||
}
|
||||
```
|
||||
|
||||
Sample `curl` command:
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" \
|
||||
http://localhost:8123/api/states/sensor.kitchen_temperature
|
||||
```
|
||||
|
||||
#### GET /api/error_log
|
||||
|
||||
Retrieve all errors logged during the current session of Home Assistant as a plaintext response.
|
||||
|
||||
```text
|
||||
15-12-20 11:02:50 homeassistant.components.recorder: Found unfinished sessions
|
||||
15-12-20 11:03:03 netdisco.ssdp: Error fetching description at http://192.168.1.1:8200/rootDesc.xml
|
||||
15-12-20 11:04:36 homeassistant.components.alexa: Received unknown intent HelpIntent
|
||||
```
|
||||
|
||||
Sample `curl` command:
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" \
|
||||
http://localhost:8123/api/error_log
|
||||
```
|
||||
|
||||
#### GET /api/camera_proxy/camera.<entity_id>
|
||||
|
||||
Returns the data (image) from the specified camera entity_id.
|
||||
|
||||
Sample `curl` command:
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" \
|
||||
http://localhost:8123/api/camera_proxy/camera.my_sample_camera?time=1462653861261 -o image.jpg
|
||||
```
|
||||
|
||||
#### POST /api/states/<entity_id>
|
||||
|
||||
Updates or creates the current state of an entity.
|
||||
|
||||
Expects a JSON object that has at least a state attribute:
|
||||
|
||||
```json
|
||||
{
|
||||
"state": "below_horizon",
|
||||
"attributes": {
|
||||
"next_rising":"2016-05-31T03:39:14+00:00",
|
||||
"next_setting":"2016-05-31T19:16:42+00:00"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The return code is 200 if the entity existed, 201 if the state of a new entity was set. A location header will be returned with the URL of the new resource. The response body will contain a JSON encoded State object.
|
||||
|
||||
```json
|
||||
{
|
||||
"attributes": {
|
||||
"next_rising":"2016-05-31T03:39:14+00:00",
|
||||
"next_setting":"2016-05-31T19:16:42+00:00"
|
||||
},
|
||||
"entity_id": "sun.sun",
|
||||
"last_changed": "2016-05-30T21:43:29.204838+00:00",
|
||||
"last_updated": "2016-05-30T21:47:30.533530+00:00",
|
||||
"state": "below_horizon"
|
||||
}
|
||||
```
|
||||
|
||||
Sample `curl` command:
|
||||
|
||||
```bash
|
||||
$ curl -X POST -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"state": "25", "attributes": {"unit_of_measurement": "°C"}}' \
|
||||
http://localhost:8123/api/states/sensor.kitchen_temperature
|
||||
```
|
||||
|
||||
#### POST /api/events/<event_type>
|
||||
|
||||
Fires an event with event_type
|
||||
|
||||
You can pass an optional JSON object to be used as `event_data`.
|
||||
|
||||
```json
|
||||
{
|
||||
"next_rising":"2016-05-31T03:39:14+00:00",
|
||||
}
|
||||
```
|
||||
|
||||
Returns a message if successful.
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Event download_file fired."
|
||||
}
|
||||
```
|
||||
|
||||
#### POST /api/services/<domain>/<service>
|
||||
|
||||
Calls a service within a specific domain. Will return when the service has been executed or after 10 seconds, whichever comes first.
|
||||
|
||||
You can pass an optional JSON object to be used as `service_data`.
|
||||
|
||||
```json
|
||||
{
|
||||
"entity_id": "light.Ceiling"
|
||||
}
|
||||
```
|
||||
|
||||
Returns a list of states that have changed while the service was being executed.
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"attributes": {},
|
||||
"entity_id": "sun.sun",
|
||||
"last_changed": "2016-05-30T21:43:32.418320+00:00",
|
||||
"state": "below_horizon"
|
||||
},
|
||||
{
|
||||
"attributes": {},
|
||||
"entity_id": "process.Dropbox",
|
||||
"last_changed": "22016-05-30T21:43:32.418320+00:00",
|
||||
"state": "on"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Sample `curl` commands:
|
||||
|
||||
Turn the light on:
|
||||
|
||||
```bash
|
||||
$ curl -X POST -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"entity_id": "switch.christmas_lights"}' \
|
||||
http://localhost:8123/api/services/switch/turn_on
|
||||
```
|
||||
|
||||
Send a MQTT message:
|
||||
|
||||
```bash
|
||||
$ curl -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "x-ha-access:YOUR_PASSWORD" \
|
||||
-d '{"payload": "OFF", "topic": "home/fridge", "retain": "True"}' \
|
||||
http://localhost:8123/api/services/mqtt/publish
|
||||
```
|
||||
|
||||
> The result will include any states that changed while the service was being executed, even if their change was the result of something else happening in the system.
|
||||
|
||||
#### POST /api/template
|
||||
|
||||
Render a Home Assistant template. [See template docs for more information.](https://www.home-assistant.io/topics/templating/)
|
||||
|
||||
```json
|
||||
{
|
||||
"template": "Paulus is at {{ states('device_tracker.paulus') }}!"
|
||||
}
|
||||
```
|
||||
|
||||
Returns the rendered template in plain text.
|
||||
|
||||
```text
|
||||
Paulus is at work!
|
||||
```
|
||||
|
||||
Sample `curl` command:
|
||||
|
||||
```bash
|
||||
$ curl -X POST -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"template": "It is {{ now }}!"}' http://localhost:8123/api/template
|
||||
```
|
||||
|
||||
#### POST /api/event_forwarding
|
||||
|
||||
Set up event forwarding to another Home Assistant instance.
|
||||
|
||||
Requires a JSON object that represents the API to forward to.
|
||||
|
||||
```javascript
|
||||
{
|
||||
"host": "machine",
|
||||
"api_password": "my_super_secret_password",
|
||||
"port": 8880 // optional
|
||||
}
|
||||
```
|
||||
|
||||
It will return a message if event forwarding was set up successfully.
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Event forwarding setup."
|
||||
}
|
||||
```
|
||||
|
||||
#### DELETE /api/event_forwarding
|
||||
|
||||
Cancel event forwarding to another Home Assistant instance.<br>
|
||||
|
||||
Requires a JSON object that represents the API to cancel forwarding to.
|
||||
|
||||
```javascript
|
||||
{
|
||||
"host": "machine",
|
||||
"api_password": "my_super_secret_password",
|
||||
"port": 8880 // optional
|
||||
}
|
||||
```
|
||||
|
||||
It will return a message if event forwarding was canceled successfully.
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "Event forwarding cancelled."
|
||||
}
|
||||
```
|
231
website/versioned_docs/version-0.72/external_api_rest_python.md
Normal file
231
website/versioned_docs/version-0.72/external_api_rest_python.md
Normal file
@ -0,0 +1,231 @@
|
||||
---
|
||||
title: REST API - Python bindings
|
||||
id: version-0.72-external_api_rest_python
|
||||
original_id: external_api_rest_python
|
||||
---
|
||||
|
||||
See the [developer documentation][devdocs] for a full overview of the documentation. The rest of this page will contain examples on how to use it.
|
||||
|
||||
[devdocs]: https://dev-docs.home-assistant.io/en/master/api/homeassistant.html#module-homeassistant.remote
|
||||
|
||||
In the package [`homeassistant.remote`](https://github.com/home-assistant/home-assistant/blob/master/homeassistant/remote.py) a Python API on top of the [HTTP API](https://www.home-assistant.io/developers/api/) can be found. If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`api` component](https://www.home-assistant.io/components/api/) to your `configuration.yaml` file to use the Python Remote API.
|
||||
|
||||
A simple way to get all current entities is to visit the "Set State" page in the "Developer Tools". For the examples below just choose one from the available entries. Here the sensor `sensor.office_temperature` and the switch `switch.livingroom_pin_2` are used.
|
||||
|
||||
First import the module and setup the basics:
|
||||
|
||||
```python
|
||||
import homeassistant.remote as remote
|
||||
|
||||
api = remote.API('127.0.0.1', 'password')
|
||||
print(remote.validate_api(api))
|
||||
```
|
||||
|
||||
### Get configuration
|
||||
|
||||
Get the current configuration of a Home Assistant instance:
|
||||
|
||||
```python
|
||||
import homeassistant.remote as remote
|
||||
|
||||
api = remote.API('127.0.0.1', 'password')
|
||||
|
||||
print(remote.get_config(api))
|
||||
```
|
||||
|
||||
### Get details about services, events, and entitites
|
||||
|
||||
The output from this is similar to the output you'd find via the frontend, using the [Developer Tools](https://www.home-assistant.io/docs/tools/dev-tools/).
|
||||
|
||||
```python
|
||||
import homeassistant.remote as remote
|
||||
|
||||
api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
|
||||
|
||||
print('-- Available services:')
|
||||
services = remote.get_services(api)
|
||||
for service in services:
|
||||
print(service['services'])
|
||||
|
||||
print('\n-- Available events:')
|
||||
events = remote.get_event_listeners(api)
|
||||
for event in events:
|
||||
print(event)
|
||||
|
||||
print('\n-- Available entities:')
|
||||
entities = remote.get_states(api)
|
||||
for entity in entities:
|
||||
print(entity)
|
||||
```
|
||||
|
||||
### Get the state of an entity
|
||||
|
||||
To get the details of a single entity, use `get_state`:
|
||||
|
||||
```python
|
||||
import homeassistant.remote as remote
|
||||
|
||||
api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
|
||||
office_temp = remote.get_state(api, 'sensor.office_temperature')
|
||||
print('{} is {} {}.'.format(
|
||||
office_temp.name, office_temp.state,
|
||||
office_temp.attributes['unit_of_measurement'])
|
||||
)
|
||||
```
|
||||
|
||||
This outputs the details which are stored for this entity, ie:
|
||||
|
||||
```bash
|
||||
Office Temperature is 19 °C.
|
||||
```
|
||||
|
||||
Switches work the same way. The only difference is that both entities have different attributes.
|
||||
|
||||
```python
|
||||
import homeassistant.remote as remote
|
||||
|
||||
api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
|
||||
switch_livingroom = remote.get_state(api, 'switch.livingroom_pin_2')
|
||||
print('{} is {}.'.format(
|
||||
switch_livingroom.name, switch_livingroom.state)
|
||||
)
|
||||
```
|
||||
|
||||
### Set the state of an entity
|
||||
|
||||
Of course, it's possible to set the state as well:
|
||||
|
||||
```python
|
||||
import homeassistant.remote as remote
|
||||
from homeassistant.const import STATE_ON
|
||||
|
||||
api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
|
||||
remote.set_state(api, 'sensor.office_temperature', new_state=123)
|
||||
remote.set_state(api, 'switch.livingroom_pin_2', new_state=STATE_ON)
|
||||
```
|
||||
|
||||
The state will be set to the new values until the next update occurs.
|
||||
|
||||
### Blinking all entities of a domain
|
||||
|
||||
If you want to turn on all entities of a domain, retrieve the service via `get_services` and act on that:
|
||||
|
||||
|
||||
```python
|
||||
import time
|
||||
import homeassistant.remote as remote
|
||||
|
||||
api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
|
||||
domain = 'switch'
|
||||
|
||||
remote.call_service(api, domain, 'turn_on')
|
||||
time.sleep(10)
|
||||
remote.call_service(api, domain, 'turn_off')
|
||||
```
|
||||
|
||||
### Control a single entity
|
||||
|
||||
To turn on or off a single switch, pass the ID of the entity:
|
||||
|
||||
```python
|
||||
import time
|
||||
import homeassistant.remote as remote
|
||||
|
||||
api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
|
||||
domain = 'switch'
|
||||
switch_name = 'switch.livingroom_pin_2'
|
||||
|
||||
remote.call_service(api, domain, 'turn_on', {'entity_id': '{}'.format(switch_name)})
|
||||
time.sleep(5)
|
||||
remote.call_service(api, domain, 'turn_off', {'entity_id': '{}'.format(switch_name)})
|
||||
```
|
||||
|
||||
### Specify a timeout
|
||||
|
||||
The default timeout for an API call with `call_service` is 5 seconds. Services
|
||||
taking longer than this to return will raise
|
||||
`homeassistant.exceptions.HomeAssistantError: Timeout`, unless provided with a
|
||||
longer timeout.
|
||||
|
||||
```python
|
||||
import homeassistant.remote as remote
|
||||
|
||||
api = remote.API('host', 'password')
|
||||
domain = 'switch'
|
||||
|
||||
# Assuming switch.timeout_switch takes 10 seconds to return
|
||||
switch_name = 'switch.timeout_switch'
|
||||
|
||||
# Raises homeassistant.exceptions.HomeAssistantError: Timeout when talking to
|
||||
remote.call_service(api, domain, 'turn_on', {'entity_id': switch_name})
|
||||
|
||||
# Runs withous exception
|
||||
remote.call_service(api, domain, 'turn_on', {'entity_id': switch_name},
|
||||
timeout=11)
|
||||
```
|
||||
|
||||
### Send a notification
|
||||
|
||||
The example uses the Jabber notification platform to send a single message to the given recipient in the `configuration.yaml` file:
|
||||
|
||||
```python
|
||||
import homeassistant.remote as remote
|
||||
|
||||
api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
|
||||
domain = 'notify'
|
||||
data = {"title":"Test", "message":"A simple test message from HA."}
|
||||
|
||||
remote.call_service(api, domain, 'jabber', data)
|
||||
```
|
||||
|
||||
## Examples
|
||||
|
||||
This section contains a couple of sample scripts.
|
||||
|
||||
### List all sensors and their value
|
||||
|
||||
If you want to see, export or list all sensor states then an easy way to do it, is to get all entities and filter for the one you are looking for.
|
||||
|
||||
```python
|
||||
import homeassistant.remote as remote
|
||||
|
||||
api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
|
||||
entities = remote.get_states(api)
|
||||
for entity in entities:
|
||||
if entity.entity_id.startswith('sensor'):
|
||||
data = remote.get_state(api, entity.entity_id)
|
||||
print('{}: {}'.format(data.attributes['friendly_name'], data.state))
|
||||
```
|
||||
|
||||
### Show difference between `last_changed` and `last_updated`
|
||||
|
||||
The documentation about the [State Objects](https://www.home-assistant.io/docs/configuration/state_object/) describes the
|
||||
`last_changed` and `last_updated` fields. This example shows how it works in practice.
|
||||
|
||||
```python
|
||||
import time
|
||||
|
||||
from prettytable import PrettyTable
|
||||
import homeassistant.remote as remote
|
||||
|
||||
api = remote.API('127.0.0.1', 'YOUR_PASSWORD')
|
||||
|
||||
ACTIONS = {
|
||||
'Create sensor': [21, 'Test'],
|
||||
'No new sensor value': [21, 'Test'],
|
||||
'New sensor value': [22, 'Test'],
|
||||
'Update attribute': [22, 'Test1'],
|
||||
}
|
||||
|
||||
output = PrettyTable(['Action', 'Last changed', 'Last updated'])
|
||||
|
||||
for key, value in ACTIONS.items():
|
||||
remote.set_state(api, 'sensor.test', new_state=value[0],
|
||||
attributes={'friendly_name': value[1]})
|
||||
data = remote.get_state(api, 'sensor.test')
|
||||
output.add_row([key, data.last_changed, data.last_updated])
|
||||
time.sleep(2)
|
||||
|
||||
print(output)
|
||||
```
|
||||
|
@ -0,0 +1,68 @@
|
||||
---
|
||||
title: Server-sent events
|
||||
id: version-0.72-external_api_server_sent_events
|
||||
original_id: external_api_server_sent_events
|
||||
---
|
||||
|
||||
The [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) feature is a one-way channel from your Home Assistant server to a client which is acting as a consumer. For a bi-directional streaming API, check out the [WebSocket API](external_api_websocket.md).
|
||||
|
||||
The URI that is generating the data is `/api/stream`.
|
||||
|
||||
A requirement on the client-side is existing support for the [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) interface.
|
||||
|
||||
There are various ways to access the stream. If you have not set an `api_password` in the [`http`](https://www.home-assistant.io/components/http/) section of your `configuration.yaml` file then you use your modern browser to read the messages. A command-line option is `curl`:
|
||||
|
||||
```bash
|
||||
$ curl -X GET -H "x-ha-access: YOUR_PASSWORD" \
|
||||
-H "Content-Type: application/json" http://localhost:8123/api/stream
|
||||
```
|
||||
|
||||
You can create a convenient view for this by creating an HTML file (`sse.html`) in the `www` folder of your Home Assistant configuration directory (`.homeassistant`). Paste this snippet into the file:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<body>
|
||||
<h1>Getting Home Assistant server events</h1>
|
||||
<div id="events"></div>
|
||||
<script type="text/javascript">
|
||||
var source = new EventSource("/api/stream?api_password=YOUR_PASSWORD");
|
||||
source.onmessage = function(event) {
|
||||
document.getElementById("events").innerHTML += event.data + "<br>";
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Visit [http://localhost:8123/local/sse.html](http://localhost:8123/local/sse.html) to see the stream of events.
|
||||
|
||||
## Examples
|
||||
|
||||
A simple way to consume server-sent events is to use a command-line http client like [httpie](https://httpie.org/). Installation info is on the site (if you use Homebrew, it's `brew install httpie`). Once installed, run this snippet from your terminal:
|
||||
|
||||
```bash
|
||||
$ http --stream http://localhost:8123/api/stream x-ha-access:YOUR_PASSWORD content-type:application/json
|
||||
```
|
||||
|
||||
### Website
|
||||
|
||||
The [home-assistant-sse](https://github.com/fabaff/home-assistant-sse) repository contains a more advanced example.
|
||||
|
||||
### Python
|
||||
|
||||
If you want to test the server-sent events without creating a website, the Python module [`sseclient` ](https://pypi.python.org/pypi/sseclient/) can help. To install (assuming Python and pip3 are already installed):
|
||||
|
||||
```bash
|
||||
$ pip3 install sseclient
|
||||
```
|
||||
|
||||
A simple script to consume SSE in Python looks like this:
|
||||
|
||||
```python
|
||||
from sseclient import SSEClient
|
||||
|
||||
messages = SSEClient('http://localhost:8123/api/stream?api_password=YOUR_PASSWORD')
|
||||
for msg in messages:
|
||||
print(msg)
|
||||
```
|
418
website/versioned_docs/version-0.72/external_api_websocket.md
Normal file
418
website/versioned_docs/version-0.72/external_api_websocket.md
Normal file
@ -0,0 +1,418 @@
|
||||
---
|
||||
title: WebSocket API
|
||||
id: version-0.72-external_api_websocket
|
||||
original_id: external_api_websocket
|
||||
---
|
||||
|
||||
Home Assistant contains a WebSocket API. This API can be used to stream information from a Home Assistant instance to any client that implements WebSocket. Implementations in different languages:
|
||||
|
||||
- [JavaScript](https://github.com/home-assistant/home-assistant-js-websocket) - powers the frontend
|
||||
- [Python](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket-client.py) - CLI client using [`asyncws`](https://async-websockets.readthedocs.io/en/latest/)
|
||||
- [JavaScript/HTML](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket.html) - WebSocket connection in your browser
|
||||
|
||||
Connect your websocket implementation to `ws://localhost:8123/api/websocket`.
|
||||
|
||||
If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`websocket_api` component](https://www.home-assistant.io/components/websocket_api/) to your `configuration.yaml` file to use the WebSocket API.
|
||||
|
||||
## Server states
|
||||
|
||||
1. Client connects.
|
||||
1. Authentication phase starts.
|
||||
- If no further authentication necessary for the user: go to 3.
|
||||
- Server sends `auth_required` message.
|
||||
- Client sends `auth` message.
|
||||
- If `auth` message correct: go to 3.
|
||||
- Server sends `auth_invalid`. Go to 6.
|
||||
1. Send `auth_ok` message
|
||||
1. Authentication phase ends.
|
||||
1. Command phase starts.
|
||||
1. Client can send commands.
|
||||
1. Server can send results of previous commands.
|
||||
1. Client or server disconnects session.
|
||||
|
||||
During the command phase, the client attaches a unique identifier to each message. The server will add this identifier to each message so that the client can link each message to its origin.
|
||||
|
||||
## Message format
|
||||
|
||||
Each API message is a JSON serialized object containing a `type` key. After the authentication phase messages also must contain an `id`, an integer that contains the number of interactions.
|
||||
|
||||
Example of an auth message:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "auth",
|
||||
"api_password": "supersecret"
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"id" 5,
|
||||
"type":"event",
|
||||
"event":{
|
||||
"data":{},
|
||||
"event_type":"test_event",
|
||||
"time_fired":"2016-11-26T01:37:24.265429+00:00",
|
||||
"origin":"LOCAL"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Authentication phase
|
||||
|
||||
When a client connects to the server, the server will test if the client is authenticated. Authentication will not be necessary if no api_password is set or if the user fulfills one of the other criteria for authentication (trusted network, password in url/header).
|
||||
|
||||
If no authentication is needed, the authentication phase will complete and the server will send an `auth_ok` message.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "auth_ok"
|
||||
}
|
||||
```
|
||||
|
||||
If authentication is necessary, the server sends out `auth_required`.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "auth_required"
|
||||
}
|
||||
```
|
||||
|
||||
This means that the next message from the client should be an auth message. You can authorize with either an API password (legacy auth) or an access token.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "auth",
|
||||
"api_password": "supersecret"
|
||||
}
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "auth",
|
||||
"access_token": "ABCDEFGH"
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
If the client supplies valid authentication, the authentication phase will complete by the server sending the `auth_ok` message:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "auth_ok"
|
||||
}
|
||||
```
|
||||
|
||||
If the data is incorrect, the server will reply with `auth_invalid` message and disconnect the session.
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "auth_invalid",
|
||||
"message": "Invalid password"
|
||||
}
|
||||
```
|
||||
|
||||
## Command phase
|
||||
|
||||
During this phase the client can give commands to the server. The server will respond to each command with a `result` message indicating when the command is done and if it was successful.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 6.
|
||||
"type": "result",
|
||||
"success": true,
|
||||
// Can contain extra result info
|
||||
"result": null
|
||||
}
|
||||
```
|
||||
|
||||
## Subscribe to events
|
||||
|
||||
The command `subscribe_events` will subscribe your client to the event bus. You can either listen to all events or to a specific event type. If you want to listen to multiple event types, you will have to send multiple `subscribe_events` commands.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 18,
|
||||
"type": "subscribe_events",
|
||||
// Optional
|
||||
"event_type": "state_changed"
|
||||
}
|
||||
```
|
||||
|
||||
The server will respond with a result message to indicate that the subscription is active.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 18,
|
||||
"type": "result",
|
||||
"success": true,
|
||||
"result": null
|
||||
}
|
||||
```
|
||||
|
||||
For each event that matches, the server will send a message of type `event`. The `id` in the message will point at the original `id` of the `listen_event` command.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 18,
|
||||
"type":"event",
|
||||
"event":{
|
||||
"data":{
|
||||
"entity_id":"light.bed_light",
|
||||
"new_state":{
|
||||
"entity_id":"light.bed_light",
|
||||
"last_changed":"2016-11-26T01:37:24.265390+00:00",
|
||||
"state":"on",
|
||||
"attributes":{
|
||||
"rgb_color":[
|
||||
254,
|
||||
208,
|
||||
0
|
||||
],
|
||||
"color_temp":380,
|
||||
"supported_features":147,
|
||||
"xy_color":[
|
||||
0.5,
|
||||
0.5
|
||||
],
|
||||
"brightness":180,
|
||||
"white_value":200,
|
||||
"friendly_name":"Bed Light"
|
||||
},
|
||||
"last_updated":"2016-11-26T01:37:24.265390+00:00"
|
||||
},
|
||||
"old_state":{
|
||||
"entity_id":"light.bed_light",
|
||||
"last_changed":"2016-11-26T01:37:10.466994+00:00",
|
||||
"state":"off",
|
||||
"attributes":{
|
||||
"supported_features":147,
|
||||
"friendly_name":"Bed Light"
|
||||
},
|
||||
"last_updated":"2016-11-26T01:37:10.466994+00:00"
|
||||
}
|
||||
},
|
||||
"event_type":"state_changed",
|
||||
"time_fired":"2016-11-26T01:37:24.265429+00:00",
|
||||
"origin":"LOCAL"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Unsubscribing from events
|
||||
|
||||
You can unsubscribe from previously created subscription events. Pass the id of the original subscription command as value to the subscription field.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "unsubscribe_events",
|
||||
"subscription": 18
|
||||
}
|
||||
```
|
||||
|
||||
The server will respond with a result message to indicate that unsubscribing was successful.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "result",
|
||||
"success": true,
|
||||
"result": null
|
||||
}
|
||||
```
|
||||
|
||||
### Calling a service
|
||||
|
||||
This will call a service in Home Assistant. Right now there is no return value. The client can listen to `state_changed` events if it is interested in changed entities as a result of a service call.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 24,
|
||||
"type": "call_service",
|
||||
"domain": "light",
|
||||
"service": "turn_on",
|
||||
// Optional
|
||||
"service_data": {
|
||||
"entity_id": "light.kitchen"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The server will indicate with a message indicating that the service is done executing.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 24,
|
||||
"type": "result",
|
||||
"success": true,
|
||||
"result": null
|
||||
}
|
||||
```
|
||||
|
||||
### Fetching states
|
||||
|
||||
This will get a dump of all the current states in Home Assistant.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "get_states"
|
||||
}
|
||||
```
|
||||
|
||||
The server will respond with a result message containing the states.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "result",
|
||||
"success": true,
|
||||
"result": [ ... ]
|
||||
}
|
||||
```
|
||||
|
||||
### Fetching config
|
||||
|
||||
This will get a dump of the current config in Home Assistant.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "get_config"
|
||||
}
|
||||
```
|
||||
|
||||
The server will respond with a result message containing the config.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "result",
|
||||
"success": true,
|
||||
"result": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
### Fetching services
|
||||
|
||||
This will get a dump of the current services in Home Assistant.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "get_services"
|
||||
}
|
||||
```
|
||||
|
||||
The server will respond with a result message containing the services.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "result",
|
||||
"success": true,
|
||||
"result": { ... }
|
||||
}
|
||||
```
|
||||
|
||||
### Fetching panels
|
||||
|
||||
This will get a dump of the current registered panels in Home Assistant.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "get_panels"
|
||||
}
|
||||
```
|
||||
|
||||
The server will respond with a result message containing the current registered panels.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "result",
|
||||
"success": true,
|
||||
"result": [ ... ]
|
||||
}
|
||||
```
|
||||
|
||||
### Fetching camera thumbnails
|
||||
|
||||
_Introduced in Home Assistant 0.69._
|
||||
|
||||
Return a b64 encoded thumbnail of a camera entity.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "camera_thumbnail"
|
||||
}
|
||||
```
|
||||
|
||||
The server will respond with a result message containing the thumbnail.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "result",
|
||||
"success": true,
|
||||
"result": {
|
||||
"content_type": "image/jpeg",
|
||||
"content": "<base64 encoded image>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Fetching media player thumbnails
|
||||
|
||||
_Introduced in Home Assistant 0.69._
|
||||
|
||||
Fetch a base64 encoded thumbnail picture for a media player.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "media_player_thumbnail",
|
||||
"entity_id": "media_player.living_room"
|
||||
}
|
||||
```
|
||||
|
||||
The server will respond with the image encoded via base64.
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 19,
|
||||
"type": "result",
|
||||
"success": true,
|
||||
"result": {
|
||||
"content_type": "image/jpeg",
|
||||
"content": "<base64 encoded image>"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Error handling
|
||||
|
||||
If an error occurs, the `success` key in the `result` message will be set to `false`. It will contain an `error` key containing an object with two keys: `code` and `message`.
|
||||
|
||||
| Code | Description |
|
||||
| ----- | ------------ |
|
||||
| 1 | A non-increasing identifier has been supplied.
|
||||
| 2 | Received message is not in expected format (voluptuous validation error).
|
||||
| 3 | Requested item cannot be found
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 12,
|
||||
"type":"result",
|
||||
"success": false,
|
||||
"error": {
|
||||
"code": 2,
|
||||
"message": "Message incorrectly formatted: expected str for dictionary value @ data['event_type']. Got 100"
|
||||
}
|
||||
}
|
||||
```
|
23
website/versioned_docs/version-0.72/frontend_add_card.md
Normal file
23
website/versioned_docs/version-0.72/frontend_add_card.md
Normal file
@ -0,0 +1,23 @@
|
||||
---
|
||||
title: Adding state card
|
||||
id: version-0.72-frontend_add_card
|
||||
original_id: frontend_add_card
|
||||
---
|
||||
|
||||
The main interface of Home Assistant is a list of the current entities and their states. For each entity in the system, a state card will be rendered. State cards will show an icon, the name of the entity, when the state has last changed and the current state or a control to interact with it.
|
||||
|
||||

|
||||
|
||||
The different card types can be found [here](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary).
|
||||
|
||||
Sensors, when not grouped, are shown as so-called badges on top of the state cards.
|
||||
|
||||

|
||||
|
||||
The different badges are located in the file [`/src/components/entity/ha-state-label-badge.js`](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/components/entity/ha-state-label-badge.js).
|
||||
|
||||
Adding a custom card type can be done with a few simple steps. For this example we will add a new state card for the domain `camera`:
|
||||
|
||||
1. Add `'camera'` to the array `DOMAINS_WITH_CARD` in the file [/common/const.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/common/const.js).
|
||||
2. Create the files `state-card-camera.js` in the folder [/state-summary/](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/state-summary).
|
||||
3. Add `import './state-card-camera.js';` to [state-card-content.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/state-summary/state-card-content.js).
|
@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Adding more info dialogs
|
||||
id: version-0.72-frontend_add_more_info
|
||||
original_id: frontend_add_more_info
|
||||
---
|
||||
|
||||
Whenever the user taps or clicks on one of the cards, a more info dialog will show. The header of this dialog will be the state card, followed by the history of this entity for the last 24 hours. Below this the more info component is rendered for that entity. The more info component can show more information or allow more ways of control.
|
||||
|
||||
<img
|
||||
src='/img/en/frontend/frontend-more-info-light.png'
|
||||
alt='The more info dialog for a light allows the user to control the color and the brightness.'
|
||||
/>
|
||||
|
||||
The instructions to add a more info dialog are very similar to adding a new card type. This example will add a new more info component for the domain `camera`:
|
||||
|
||||
1. Add `'camera'` to the array `DOMAINS_WITH_MORE_INFO` in the file [/common/entity/state_more_info_type.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/common/entity/state_more_info_type.js).
|
||||
2. Create the files `more-info-camera.js` in the folder [/dialogs/more-info/controls](https://github.com/home-assistant/home-assistant-polymer/tree/master/src/dialogs/more-info/controls).
|
||||
3. Add `import './more-info-camera.js';` to [/dialogs/more-info/controls/more-info-content.js](https://github.com/home-assistant/home-assistant-polymer/blob/master/src/dialogs/more-info/controls/more-info-content.js)
|
@ -0,0 +1,131 @@
|
||||
---
|
||||
title: Extending the WebSocket API
|
||||
id: version-0.72-frontend_add_websocket_api
|
||||
original_id: frontend_add_websocket_api
|
||||
---
|
||||
|
||||
As a component you might have information that you want to make available to the frontend. For example, the media player will want to make album covers available for the frontend to show. Our frontend is communicating with the backend over the websocket API, which can be extended with custom commands.
|
||||
|
||||
## Registering a command (Python)
|
||||
|
||||
To register a command, you need to have a message type, a message schema and a message handler. Your component does not have to add the websocket API as a dependency. You register your command, and if the user is using the websocket API, the command will be made available.
|
||||
|
||||
### Message Types
|
||||
|
||||
Message types are made up the domain and the message type, seperated by a forward slash. In the below example, we're defining `media_player/thumbnail`.
|
||||
|
||||
```python
|
||||
# The type of the message
|
||||
WS_TYPE_MEDIA_PLAYER_THUMBNAIL = 'media_player/thumbnail'
|
||||
```
|
||||
|
||||
### Message Schema
|
||||
|
||||
The message schema defines what type of data we expect when the message is invoked. It is defined as a voluptuous schema and has to extend the base web socket command schema.
|
||||
|
||||
```python
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components import websocket_api
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
|
||||
|
||||
# The schema for the message
|
||||
SCHEMA_WEBSOCKET_GET_THUMBNAIL = \
|
||||
websocket_api.BASE_COMMAND_MESSAGE_SCHEMA.extend({
|
||||
'type': WS_TYPE_MEDIA_PLAYER_THUMBNAIL,
|
||||
# The entity that we want to retrieve the thumbnail for.
|
||||
'entity_id': cv.entity_id
|
||||
})
|
||||
```
|
||||
|
||||
### Defining a handler
|
||||
|
||||
Message handlers are callback functions that are run inside the event loop. If you want to do I/O or have to wait for your result, create a new function and queue it up using `hass.async_add_job`. This is done so that the websocket API can get back to handling the next message as soon as possible.
|
||||
|
||||
#### Sending a direct response
|
||||
|
||||
If you are defining a command that is querying simple information, you might be able to fulfill the request while the handler is being called by the websocket API. To do this, use `connection.to_write.put_nowait`.
|
||||
|
||||
```python
|
||||
@callback
|
||||
def websocket_handle_thumbnail(hass, connection, msg):
|
||||
"""Handle getting a thumbnail."""
|
||||
|
||||
# We know the answer without having to fetch any information,
|
||||
# so we send it directly.
|
||||
connection.to_write.put_nowait(websocket_api.result_message(msg['id'], {
|
||||
'thumbnail': 'http://via.placeholder.com/350x150'
|
||||
}))
|
||||
```
|
||||
|
||||
#### Sending a delayed response
|
||||
|
||||
If your command needs to interact with the network, a device or needs to compute information, you will need to queue a job to do the work and send the response. To do this, use `connection.send_message_outside`.
|
||||
|
||||
```python
|
||||
@callback
|
||||
def websocket_handle_thumbnail(hass, connection, msg):
|
||||
"""Handle get media player cover command."""
|
||||
# Retrieve media player using passed in entity id.
|
||||
player = hass.data[DOMAIN].get_entity(msg['entity_id'])
|
||||
|
||||
# If the player does not exist, send an error message.
|
||||
if player is None:
|
||||
connection.to_write.put_nowait(websocket_api.error_message(
|
||||
msg['id'], 'entity_not_found', 'Entity not found'))
|
||||
return
|
||||
|
||||
# Define a function to be enqueued.
|
||||
async def send_image():
|
||||
"""Send image."""
|
||||
data, content_type = await player.async_get_media_image()
|
||||
|
||||
# No media player thumbnail available
|
||||
if data is None:
|
||||
connection.send_message_outside(websocket_api.error_message(
|
||||
msg['id'], 'thumbnail_fetch_failed',
|
||||
'Failed to fetch thumbnail'))
|
||||
return
|
||||
|
||||
connection.send_message_outside(websocket_api.result_message(
|
||||
msg['id'], {
|
||||
'content_type': content_type,
|
||||
'content': base64.b64encode(data).decode('utf-8')
|
||||
}))
|
||||
|
||||
# Player exist. Queue up a job to send the thumbnail.
|
||||
hass.async_add_job(send_image())
|
||||
```
|
||||
|
||||
### Registering with the Websocket API
|
||||
|
||||
With all pieces defined, it's time to register the command. This is done inside your setup method.
|
||||
|
||||
```python
|
||||
async def async_setup(hass, config):
|
||||
"""Setup of your component."""
|
||||
hass.components.websocket_api.async_register_command(
|
||||
WS_TYPE_MEDIA_PLAYER_THUMBNAIL, websocket_handle_thumbnail,
|
||||
SCHEMA_WEBSOCKET_GET_THUMBNAIL)
|
||||
```
|
||||
|
||||
## Calling the command from the frontend (JavaScript)
|
||||
|
||||
With your command defined, it's time to call it from the frontend! This is done using JavaScript. You will need access to the `hass` object which holds the WebSocket connection to the backend. Then just call `hass.connection.sendMessagePromise`. This will return a promise that will resolve if the command succeeds and errors if the command fails.
|
||||
|
||||
```js
|
||||
hass.connection.sendMessagePromise({
|
||||
type: 'media_player/thumbnail',
|
||||
entity_id: 'media_player.living_room_tv',
|
||||
}).then(
|
||||
(resp) => {
|
||||
console.log('Message success!', resp.result);
|
||||
},
|
||||
(err) => {
|
||||
console.error('Message failed!', err);
|
||||
}
|
||||
);
|
||||
```
|
||||
|
||||
If your command is not sending a response, you can use `hass.connection.sendMessage`.
|
64
website/versioned_docs/version-0.72/frontend_architecture.md
Normal file
64
website/versioned_docs/version-0.72/frontend_architecture.md
Normal file
@ -0,0 +1,64 @@
|
||||
---
|
||||
title: Home Assistant Frontend Architecture
|
||||
sidebar_label: Architecture
|
||||
id: version-0.72-frontend_architecture
|
||||
original_id: frontend_architecture
|
||||
---
|
||||
|
||||
The Home Assistant frontend is built using web components. This is a modern web technology allowing us to encapsulate templates, styling and logic into a single file and expose it as an HTML tag in the browser. These componens are composable, allowing a very dynamic and powerful foundation of our application.
|
||||
|
||||
## Structure
|
||||
|
||||
The Home Assistant frontend can be broken up in 4 parts:
|
||||
|
||||
### Bootstrap
|
||||
|
||||
File: `src/entrypoints/core.js`
|
||||
|
||||
This is a very tiny script which is the first thing that is loaded on the page. It is responsible for checking for authentication credentials and setting up the websocket connection with the backend.
|
||||
|
||||
The script allows us to start downloading the data while also downloading the rest of the UI in parallel.
|
||||
|
||||
### App shell
|
||||
|
||||
File: `src/entrypoints/app.js`
|
||||
|
||||
This is everything that is required to render the sidebar and handle the routing.
|
||||
|
||||
### Panels
|
||||
|
||||
Folder: `src/panels/`
|
||||
|
||||
Each page in Home Assistant is a panel. Components can register extra panels to be shown to the user. Examples of panels are "states", "map", "logbook" and "history".
|
||||
|
||||
### More info dialog
|
||||
|
||||
Folder: `src/dialogs/more-info`
|
||||
|
||||
This is a dialog that allows users to see more information about an entity and control it's state.
|
||||
|
||||
The more info dialog can be triggered from any component in the app by firing a DOM event `hass-more-info` with as detail `{ entityId: 'light.kitchen' }`.
|
||||
|
||||
## Data Flow
|
||||
|
||||
The frontend leverages the [Websocket API](external_api_websocket.md) and the [Rest API](external_api_rest.md) to interact with Home Assistant.
|
||||
|
||||
The data is made available as the `hass` property which is passed down to every component. The `hass` property contains the whole application state and has methods to call APIs.
|
||||
|
||||
We use a unidirectional data flow (like Flux, Redux). When you make a change in the backend (like turning on a light), the `hass` object will be updated at the root of the application and will be made available to every component that needs it.
|
||||
|
||||
## Routing
|
||||
|
||||
The frontend uses decentralized routing. Each component only knows enough about the routing to know how to handle the part it's repsonsible for. Further routing is passed down the component tree.
|
||||
|
||||
For example, the `<home-assistant>` main component will look at the first part of the url to decide which panel should be loaded. Each panel can have its own mapping between the url and what content to show.
|
||||
|
||||
For the routing, we use the [`<app-route>`](https://www.polymer-project.org/3.0/toolbox/routing) web component.
|
||||
|
||||
## Bundling
|
||||
|
||||
We use Webpack to bundle up the application. We have various gulp scripts to help with generating the icon set and the index.html.
|
||||
|
||||
We're aggresively code splitting our application by leveraging the dynamic import syntax (`import('path/to/some/file.js')`). When encountering an `import()`, Webpack will split the code into different chunks and makes sure that they are loaded when needed.
|
||||
|
||||
|
@ -0,0 +1,84 @@
|
||||
---
|
||||
title: Creating custom panels
|
||||
id: version-0.72-frontend_creating_custom_panels
|
||||
original_id: frontend_creating_custom_panels
|
||||
---
|
||||
|
||||
Panels are pages that show information within Home Assistant and can allow controlling it. Panels are linked from the sidebar and rendered full screen. They have real-time access to the Home Assistant object via JavaScript. Examples of panels in the app are Map, Logbook and History.
|
||||
|
||||
Besides components registering panels, users can also register panels using the `panel_custom` component. This allows users to quickly build their own custom interfaces for Home Assistant.
|
||||
|
||||
## Before you get started
|
||||
|
||||
The Home Assistant user interface is currently served to browsers in modern JavaScript and older JavaScript (ES5). The older version has a wider browser support but that comes at a cost of size, performance and more difficult to get started building panels for authors.
|
||||
|
||||
We therefore advise you to set up Home Assistant to serve the modern version of the frontend so that you won't need any build tools while developing. If you realize that your audience requires both, you can add a transpilation step in the future. To set up your frontend to always serve the latest version, add this to your config:
|
||||
|
||||
```
|
||||
frontend:
|
||||
javascript_version: latest
|
||||
```
|
||||
|
||||
## Building your first panel
|
||||
|
||||
Create a file called `hello.html` in your <config dir>/panels/.
|
||||
|
||||
The `hello.html` contains the needed building blocks to create the elements inside the view.
|
||||
|
||||
```html
|
||||
<dom-module id='ha-panel-hello'>
|
||||
<template>
|
||||
<style>
|
||||
p {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
<p>Hello {{who}}. Greetings from Home Assistant.</p>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
class HaPanelHello extends Polymer.Element {
|
||||
static get is() { return 'ha-panel-hello'; }
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
// Home Assistant object
|
||||
hass: Object,
|
||||
// If should render in narrow mode
|
||||
narrow: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
// If sidebar is currently shown
|
||||
showMenu: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
// Home Assistant panel info
|
||||
// panel.config contains config passed to register_panel serverside
|
||||
panel: Object,
|
||||
who: {
|
||||
type: String,
|
||||
computed: 'computeWho(panel)',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
computeWho(panel) {
|
||||
return panel && panel.config && panel.config.who ? panel.config.who : 'World';
|
||||
}
|
||||
}
|
||||
customElements.define(HaPanelHello.is, HaPanelHello);
|
||||
</script>
|
||||
```
|
||||
|
||||
Create an entry for the new panel in your `configuration.yaml` file:
|
||||
|
||||
```yaml
|
||||
panel_custom:
|
||||
- name: hello
|
||||
sidebar_title: Hello World
|
||||
sidebar_icon: mdi:hand-pointing-right
|
||||
url_path: hello
|
||||
```
|
@ -0,0 +1,120 @@
|
||||
---
|
||||
title: Creating custom UI
|
||||
id: version-0.72-frontend_creating_custom_ui
|
||||
original_id: frontend_creating_custom_ui
|
||||
---
|
||||
|
||||
### State card
|
||||
|
||||
If you would like to use your own [State card](frontend_add_card.md) without merging your code into [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer/) you can create your own implementation.
|
||||
|
||||
Put the element source file and its dependencies in `www/custom_ui/` directory under your Home Assistant [configuration](https://www.home-assistant.io/docs/configuration/) directory.
|
||||
|
||||
For example if creating a state card for the `light` domain named `state-card-my-custom-light` put `state-card-my-custom-light.html` in `www/custom_ui/`.
|
||||
|
||||
That file should implement `<state-card-my-custom-light>` tag with Polymer.
|
||||
|
||||
In `state-card-my-custom-light.html` you should use `<link rel="import">` to import all the dependencies **not** used by Home Assistant's UI.
|
||||
Do not import any dependencies used by the Home Assistant UI.
|
||||
Importing those will work in `development: 1` mode, but will fail in production mode.
|
||||
|
||||
1. In the `customize:` section of the `configuration.yaml` file put `custom_ui_state_card: state-card-my-custom-light`.
|
||||
2. In the `frontend` section use `extra_html_url` to specify the URL to load.
|
||||
|
||||
Example:
|
||||
|
||||
`configuration.yaml`:
|
||||
|
||||
```yaml
|
||||
homeassistant:
|
||||
customize:
|
||||
light.bedroom:
|
||||
custom_ui_state_card: state-card-my-custom-light
|
||||
|
||||
frontend:
|
||||
extra_html_url:
|
||||
- /local/custom_ui/state-card-my-custom-light.html
|
||||
```
|
||||
|
||||
`www/custom_ui/state-card-my-custom-light.html`:
|
||||
|
||||
```html
|
||||
<script>
|
||||
{
|
||||
// show the version of your custom UI in the HA dev info panel (HA 0.66.0+):
|
||||
const _NAME = 'My custom light';
|
||||
const _URL = 'https://home-assistant.io/developers/frontend_creating_custom_ui/';
|
||||
const _VERSION = '20180312';
|
||||
|
||||
if (!window.CUSTOM_UI_LIST) window.CUSTOM_UI_LIST = [];
|
||||
window.CUSTOM_UI_LIST.push({
|
||||
name: _NAME,
|
||||
url: _URL,
|
||||
version: _VERSION
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<dom-module id='state-card-my-custom-light'>
|
||||
<template>
|
||||
<style>
|
||||
|
||||
</style>
|
||||
<textarea>[[_toStr(stateObj)]]</textarea>
|
||||
</template>
|
||||
</dom-module>
|
||||
|
||||
<script>
|
||||
class StateCardMyCustomLight extends Polymer.Element {
|
||||
static get is() { return 'state-card-my-custom-light'; }
|
||||
|
||||
static get properties() {
|
||||
return {
|
||||
// Home Assistant object
|
||||
hass: Object,
|
||||
// inDialog is true if shown as more-info-card
|
||||
inDialog: {
|
||||
type: Boolean,
|
||||
value: false,
|
||||
},
|
||||
// includes state, config and more information of the entity
|
||||
stateObj: Object,
|
||||
};
|
||||
}
|
||||
|
||||
_toStr(obj) {
|
||||
return JSON.stringify(obj, null, 2);
|
||||
}
|
||||
}
|
||||
customElements.define(StateCardMyCustomLight.is, StateCardMyCustomLight);
|
||||
</script>
|
||||
```
|
||||
|
||||
> Some browsers don't support latest ECMAScript standards, these require a separate ES5 compatible file (`extra_html_url_es5`).
|
||||
|
||||
For more possibilities, see the [Custom UI section](https://www.home-assistant.io/cookbook/#user-interface) on our Examples page.
|
||||
|
||||
### More info dialog
|
||||
|
||||
_Introduced in Home Assistant 0.69._
|
||||
|
||||
Similar to the custom State card, if you would like to use your own [More info dialog](frontend_add_more_info.md) you can create your own implementation.
|
||||
|
||||
Following a similar example, if creating a more info dialog a light named `more-info-my-custom-light` put `more-info-my-custom-light.html` in `www/custom_ui/`.
|
||||
|
||||
1. In the `customize:` section of the `configuration.yaml` file put `custom_ui_more_info: more-info-my-custom-light`.
|
||||
2. In the `frontend` section use `extra_html_url` to specify the URL to load.
|
||||
|
||||
Example:
|
||||
|
||||
`configuration.yaml`:
|
||||
|
||||
```yaml
|
||||
homeassistant:
|
||||
customize:
|
||||
light.bedroom:
|
||||
custom_ui_more_info: more-info-my-custom-light
|
||||
|
||||
frontend:
|
||||
extra_html_url:
|
||||
- /local/custom_ui/more-info-my-custom-light.html
|
||||
```
|
88
website/versioned_docs/version-0.72/frontend_development.md
Normal file
88
website/versioned_docs/version-0.72/frontend_development.md
Normal file
@ -0,0 +1,88 @@
|
||||
---
|
||||
title: Frontend development
|
||||
sidebar_label: Development
|
||||
id: version-0.72-frontend_development
|
||||
original_id: frontend_development
|
||||
---
|
||||
|
||||
The Home Assistant frontend is built using web components and powered by the [Polymer](https://www.polymer-project.org/) framework.
|
||||
|
||||
> Do not use development mode in production. Home Assistant uses aggressive caching to improve the mobile experience. This is disabled during development so that you do not have to restart the server in between changes.
|
||||
|
||||
## Setting up the environment
|
||||
|
||||
> All commands below need to be run from inside the home-assistant-polymer repository.
|
||||
|
||||
### Getting the code
|
||||
|
||||
First step is to git clone the [home-assistant-polymer repository][hass-polymer]. You can place the repository anywhere on your system.
|
||||
|
||||
```bash
|
||||
$ git clone https://github.com/home-assistant/home-assistant-polymer.git
|
||||
$ cd home-assistant-polymer
|
||||
```
|
||||
|
||||
### Configuring Home Assistant
|
||||
|
||||
Next step is to configure Home Assistant to use the development mode for the frontend. Do this by updating the frontend config in your `configuration.yaml` and set the path to the home-assistant-polymer repository that you cloned in the last step:
|
||||
|
||||
```yaml
|
||||
frontend:
|
||||
# Example absolute path: /home/paulus/dev/hass/home-assistant-polymer
|
||||
development_repo: <absolute path to home-assistant-polymer repo>
|
||||
```
|
||||
|
||||
### Installing Node.js
|
||||
|
||||
Node.js is required to build the frontend. The preferred method of installing node.js is with [nvm](https://github.com/creationix/nvm). Install nvm using the instructions in the [README](https://github.com/creationix/nvm#install-script), and install the correct node.js by running the following command:
|
||||
|
||||
```bash
|
||||
$ nvm install
|
||||
```
|
||||
|
||||
[Yarn](https://yarnpkg.com/en/) is used as the package manager for node modules. [Install yarn using the instructions here.](https://yarnpkg.com/en/docs/install)
|
||||
|
||||
Next, development dependencies need to be installed to bootstrap the frontend development environment. First activate the right Node version and then download all the dependencies:
|
||||
|
||||
```bash
|
||||
$ nvm use
|
||||
$ script/bootstrap
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
During development, you will need to run the development script to maintain a development build of the frontend that auto updates when you change any of the source files. To run this server, run:
|
||||
|
||||
```bash
|
||||
$ nvm use
|
||||
$ script/develop
|
||||
```
|
||||
|
||||
## Creating pull requests
|
||||
|
||||
If you're planning on issuing a PR back to the Home Assistant codebase you need to fork the polymer project and add your fork as a remote to the Home Assistant Polymer repo.
|
||||
|
||||
```bash
|
||||
$ git remote add fork <github URL to your fork>
|
||||
```
|
||||
|
||||
When you've made your changes and are ready to push them change to the working directory for the polymer project and then push your changes
|
||||
|
||||
``` bash
|
||||
$ git add -A
|
||||
$ git commit -m "Added new feature X"
|
||||
$ git push -u fork HEAD
|
||||
```
|
||||
|
||||
## Building the Polymer frontend
|
||||
|
||||
If you're making changes to the way the frontend is packaged, it might be necessary to try out a new packaged build of the frontend in the main repository (instead of pointing it at the frontend repo). To do so, first build a production version of the frontend by running `script/build_frontend`.
|
||||
|
||||
To test it out inside Home assistant, run the following command from the main Home Assistant repository:
|
||||
|
||||
```bash
|
||||
$ pip3 install -e /path/to/home-assistant-polymer/
|
||||
$ hass --skip-pip
|
||||
```
|
||||
|
||||
[hass-polymer]: https://github.com/home-assistant/home-assistant-polymer
|
12
website/versioned_docs/version-0.72/frontend_index.md
Normal file
12
website/versioned_docs/version-0.72/frontend_index.md
Normal file
@ -0,0 +1,12 @@
|
||||
---
|
||||
title: Home Assistant Frontend
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-frontend_index
|
||||
original_id: frontend_index
|
||||
---
|
||||
|
||||
The Home Assistant frontend allows users to browse and control the state of their house, manage their automations and configure integrations.
|
||||
|
||||
The frontend is designed as a mobile-first experience. It is a progressive web application and offers an app-like experience to our users.
|
||||
|
||||

|
@ -0,0 +1,35 @@
|
||||
---
|
||||
title: Add-On Communication
|
||||
id: version-0.72-hassio_addon_communication
|
||||
original_id: hassio_addon_communication
|
||||
---
|
||||
|
||||
There are different ways for communication between add-ons inside Hass.io.
|
||||
|
||||
## Network
|
||||
|
||||
We use an internal network that allows to communicate with every add-on, even to/from Home Assistant, by using its name or alias. Only the add-ons which run on the host network are a bit limited. These can talk with all internal add-ons by their name but all other add-on can't address these add-on by name - using an alias works for both!
|
||||
|
||||
Name/alias are used for communication inside Hass.io.
|
||||
The name is generated using the following format: `{REPO}_{SLUG}`, e.g., `local_xy` or `3283fh_myaddon`. In this example, `{SLUG}` is defined in an add-ons `config.json`. You can use this name also as DNS name but you need replace the `_` with `-` to have a valid hostname. If an add-on is installed locally, `{REPO}` will be `local`. If the add-on is installed from a Github repository, `{REPO}` is a hashed identifier generated from the GitHub repository's URL (ex: https://github.com/xy/my_hassio_addons). See [here](https://github.com/home-assistant/hassio/blob/587047f9d648b8491dc8eef17dc6777f81938bfd/hassio/addons/utils.py#L17) to understand how this identifier is generated. Note that this identifier is required in certain service calls that use the [Hass.io add-on API][hassio-addon-api]. You can view the repository identifiers for all currently installed add-ons via a GET request to the hassio API `addons` endpoint.
|
||||
|
||||
Use `hassio` for communication with the internal API.
|
||||
|
||||
## Home Assistant
|
||||
|
||||
An add-on can talk to the [Home Assistant API][hass-api] using the internal proxy. That makes it very easy to communicate with the API without knowing the password, port or any other information of the Home Assistant instance. Use this URL: `http://hassio/homeassistant/api` and internal communication is redirected to the right place. The next stept is to add `homeassistant_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN` and use this as Home-Assistant password.
|
||||
|
||||
There is also a proxy for the [Home Assistant Websocket API][hass-websocket]. It works like the API proxy above and requires `HASSIO_TOKEN` as password. Use this URL: `http://hassio/homeassistant/websocket`.
|
||||
|
||||
It is also possible to talk direct to the Home Assistant instance which is named `homeassistant` over the internal network. But you need to know the configuration that is used by the running instance.
|
||||
|
||||
We have severals services for Hass.io inside Home Assistant to run tasks. To send data over STDIN to an add-on use the `hassio.addon_stdin` service.
|
||||
|
||||
## Hass.io API
|
||||
|
||||
To enables calls to the [Hass.io API][hassio-api], add `hassio_api: true` to `config.json` and read the environment variable `HASSIO_TOKEN`. Now you can use the API over the URL: `http://hassio/`. Use the `HASSIO_TOKEN` with header `X-HASSIO-KEY`.
|
||||
|
||||
[hass-api]: https://www.home-assistant.io/developers/rest_api/
|
||||
[hass-websocket]: https://www.home-assistant.io/developers/websocket_api/
|
||||
[hassio-api]: https://github.com/home-assistant/hassio/blob/master/API.md
|
||||
[hassio-addon-api]: https://github.com/home-assistant/hassio/blob/dev/API.md#restful-for-api-addons
|
202
website/versioned_docs/version-0.72/hassio_addon_config.md
Normal file
202
website/versioned_docs/version-0.72/hassio_addon_config.md
Normal file
@ -0,0 +1,202 @@
|
||||
---
|
||||
title: Add-On Configuration
|
||||
id: version-0.72-hassio_addon_config
|
||||
original_id: hassio_addon_config
|
||||
---
|
||||
|
||||
Each add-on is stored in a folder. The file structure looks like this:
|
||||
|
||||
```text
|
||||
addon_name/
|
||||
build.json
|
||||
CHANGELOG.md
|
||||
config.json
|
||||
Dockerfile
|
||||
icon.png
|
||||
logo.png
|
||||
README.md
|
||||
run.sh
|
||||
```
|
||||
|
||||
## Add-on script
|
||||
|
||||
As with every Docker container, you will need a script to run when the container is started. A user might run many add-ons, so it is encouraged to try to stick to Bash scripts if you're doing simple things.
|
||||
|
||||
When developing your script:
|
||||
|
||||
- `/data` is a volume for persistent storage.
|
||||
- `/data/options.json` contains the user configuration. You can use `jq` inside your shell script to parse this data. However, you might have to install `jq` as a separate package in your container (see `Dockerfile` below).
|
||||
|
||||
```bash
|
||||
CONFIG_PATH=/data/options.json
|
||||
|
||||
TARGET="$(jq --raw-output '.target' $CONFIG_PATH)"
|
||||
```
|
||||
|
||||
So if your `options` contain
|
||||
```json
|
||||
{ "target": "beer" }
|
||||
```
|
||||
then there will be a variable `TARGET` containing `beer` in the environment of your bash file afterwards.
|
||||
|
||||
## Add-on Docker file
|
||||
|
||||
All add-ons are based on Alpine Linux 3.6. Hass.io will automatically substitute the right base image based on the machine architecture. Add `tzdata` if you need run in a different timezone. `tzdata` Is is already added to our base images.
|
||||
|
||||
```
|
||||
ARG BUILD_FROM
|
||||
FROM $BUILD_FROM
|
||||
|
||||
ENV LANG C.UTF-8
|
||||
|
||||
# Install requirements for add-on
|
||||
RUN apk add --no-cache jq
|
||||
|
||||
# Copy data for add-on
|
||||
COPY run.sh /
|
||||
RUN chmod a+x /run.sh
|
||||
|
||||
CMD [ "/run.sh" ]
|
||||
```
|
||||
|
||||
If you don't use local build on device or our build script, make sure that the Dockerfile have also a set of labels include:
|
||||
```
|
||||
LABEL io.hass.version="VERSION" io.hass.type="addon" io.hass.arch="armhf|aarch64|i386|amd64"
|
||||
```
|
||||
|
||||
It is possible to use own base image with `build.json` or if you do not need support for automatic multi-arch building you can also use a simple docker `FROM`.
|
||||
|
||||
### Build Args
|
||||
|
||||
We support the following build arguments by default:
|
||||
|
||||
| ARG | Description |
|
||||
|-----|-------------|
|
||||
| BUILD_FROM | Hold image for dynamic builds or buildings over our systems.
|
||||
| BUILD_VERSION | Add-on version (read from `config.json`).
|
||||
| BUILD_ARCH | Hold current build arch inside.
|
||||
|
||||
## Add-on config
|
||||
|
||||
The config for an add-on is stored in `config.json`.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "xy",
|
||||
"version": "1.2",
|
||||
"slug": "folder",
|
||||
"description": "long description",
|
||||
"arch": ["amd64"],
|
||||
"url": "website with more information about add-on (ie a forum thread for support)",
|
||||
"startup": "application",
|
||||
"boot": "auto",
|
||||
"ports": {
|
||||
"123/tcp": 123
|
||||
},
|
||||
"map": ["config:rw", "ssl"],
|
||||
"options": {},
|
||||
"schema": {},
|
||||
"image": "repo/{arch}-my-custom-addon"
|
||||
}
|
||||
```
|
||||
|
||||
| Key | Type | Required | Description |
|
||||
| --- | ---- | -------- | ----------- |
|
||||
| name | string | yes | Name of the add-on
|
||||
| version | string | yes | Version of the add-on
|
||||
| slug | string | yes | Slug of the add-on
|
||||
| description | string | yes | Description of the add-on
|
||||
| arch | list | no | List of supported arch: `armhf`, `aarch64`, `amd64`, `i386`. Default all.
|
||||
| url | url | no | Homepage of the addon. Here you can explain the add-ons and options.
|
||||
| startup | bool | yes | `initialize` will start addon on setup of Hass.io. `system` is for things like databases and not dependent on other things. `services` will start before Home Assistant, while `application` is started afterwards. Finally `once` is for applications that don't run as a daemon.
|
||||
| webui | string | no | A URL for web interface of this add-on. Like `http://[HOST]:[PORT:2839]/dashboard`, the port needs the internal port, which will be replaced with the effective port. It is also possible to bind the proto part to a config options with: `[PROTO:option_name]://[HOST]:[PORT:2839]/dashboard` and he lookup if they is True and going to `https`.
|
||||
| boot | string | yes | `auto` by system and manual or only `manual`
|
||||
| ports | dict | no | Network ports to expose from the container. Format is `"container-port/type": host-port`.
|
||||
| host_network | bool | no | If that is True, the add-on run on host network.
|
||||
| host_ipc | bool | no | Default False. Allow to share the IPC namespace with others.
|
||||
| host_dbus | bool | no | Default False. Map Host dbus service into add-on.
|
||||
| devices | list | no | Device list to map into the add-on. Format is: `<path_on_host>:<path_in_container>:<cgroup_permissions>`. i.e. `/dev/ttyAMA0:/dev/ttyAMA0:rwm`
|
||||
| auto_uart | bool | no | Default False. Auto mapping all UART/Serial device from host into add-on.
|
||||
| hassio_api | bool | no | This add-on can access to Hass.io REST API. It set the host alias `hassio`.
|
||||
| homeassistant_api | bool | no | This add-on can access to Hass.io Home-Assistant REST API proxy. Use `http://hassio/homeassistant/api`.
|
||||
| privileged | list | no | Privilege for access to hardware/system. Available access: `NET_ADMIN`, `SYS_ADMIN`, `SYS_RAWIO`, `SYS_TIME`, `SYS_NICE`
|
||||
| apparmor | bool/string | no | Enable or disable AppArmor support. If it is enable, you can also use custom profiles with the name of the profile.
|
||||
| map | list | no | List of maps for additional Hass.io folders. Possible values: `config`, `ssl`, `addons`, `backup`, `share`. Defaults to `ro`, which you can change by adding `:rw` to the end of the name.
|
||||
| environment | dict | no | A dict of environment variable to run add-on.
|
||||
| audio | bool | no | Boolean. Mark this add-on to use internal an audio system. The ALSA configuration for this add-on will be mount automatic.
|
||||
| gpio | bool | no | Boolean. If this is set to True, `/sys/class/gpio` will map into add-on for access to GPIO interface from kernel. Some library need also `/dev/mem` and `SYS_RAWIO` for read/write access to this device.
|
||||
| devicetree | bool | no | Boolean. If this is set to True, `/sys/firmware/devicetree` will map into add-on.
|
||||
| stdin | bool | no | Boolean. If that is enable, you can use the STDIN with Hass.io API.
|
||||
| legacy | bool | no | Boolean. If the docker image have no hass.io labels, you can enable the legacy mode to use the config data.
|
||||
| options | dict | yes | Default options value of the add-on
|
||||
| schema | dict | yes | Schema for options value of the add-on. It can be `False` to disable schema validation and use custom options.
|
||||
| image | string | no | For use with Docker Hub.
|
||||
| timeout | integer | no | Default 10 (second). The timeout to wait until the docker is done or will be killed.
|
||||
| tmpfs | string | no | Mount a tmpfs file system in `/tmpfs`. Valide format for this option is : `size=XXXu,uid=N,rw`. Size is mandatory, valid units (`u`) are `k`, `m` and `g` and `XXX` has to be replaced by a number. `uid=N` (with `N` the uid number) and `rw` are optional.
|
||||
|
||||
### Options / Schema
|
||||
|
||||
The `options` dictionary contains all available options and their default value. Set the default value to `null` if the value is required to be given by the user before the add-on can start, and it show it inside default values. Only nested arrays and dictionaries are supported with a deep of two size. If you want make an option optional, put `?` to the end of data type, otherwise it will be a required value.
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "custom things",
|
||||
"logins": [
|
||||
{ "username": "beer", "password": "123456" },
|
||||
{ "username": "cheep", "password": "654321" }
|
||||
],
|
||||
"random": ["haha", "hihi", "huhu", "hghg"],
|
||||
"link": "http://example.com/",
|
||||
"size": 15,
|
||||
"count": 1.2
|
||||
}
|
||||
```
|
||||
|
||||
The `schema` looks like `options` but describes how we should validate the user input. For example:
|
||||
|
||||
```json
|
||||
{
|
||||
"message": "str",
|
||||
"logins": [
|
||||
{ "username": "str", "password": "str" }
|
||||
],
|
||||
"random": ["match(^\w*$)"],
|
||||
"link": "url",
|
||||
"size": "int(5,20)",
|
||||
"count": "float",
|
||||
"not_need": "str?"
|
||||
}
|
||||
```
|
||||
|
||||
We support:
|
||||
- str
|
||||
- bool
|
||||
- int / int(min,) / int(,max) / int(min,max)
|
||||
- float / float(min,) / float(,max) / float(min,max)
|
||||
- email
|
||||
- url
|
||||
- port
|
||||
- match(REGEX)
|
||||
|
||||
## Add-on extended build
|
||||
|
||||
Additional build options for an add-on is stored in `build.json`. This file will be read from our build systems.
|
||||
You need this only, if you not use the default images or need additionals things.
|
||||
|
||||
```json
|
||||
{
|
||||
"build_from": {
|
||||
"armhf": "mycustom/base-image:latest"
|
||||
},
|
||||
"squash": false,
|
||||
"args": {
|
||||
"my_build_arg": "xy"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Key | Required | Description |
|
||||
| --- | -------- | ----------- |
|
||||
| build_from | no | A dictionary with the hardware architecture as the key and the base Docker image as value.
|
||||
| squash | no | Default `False`. Be carfully with this option, you can not use the image for caching stuff after that!
|
||||
| args | no | Allow to set additional Docker build arguments as a dictionary.
|
18
website/versioned_docs/version-0.72/hassio_addon_index.md
Normal file
18
website/versioned_docs/version-0.72/hassio_addon_index.md
Normal file
@ -0,0 +1,18 @@
|
||||
---
|
||||
title: Developing an add-on
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-hassio_addon_index
|
||||
original_id: hassio_addon_index
|
||||
---
|
||||
|
||||
Add-ons for Hass.io allow the user to extend the functionality around Home Assistant. This can be running an application that Home Assistant can integrate with (like an MQTT broker) or to share the configuration via Samba for easy editing from other computers. Add-ons can be configured via the Hass.io panel in Home Assistant.
|
||||
|
||||
Under the hood, add-ons are Docker images published in [Docker Hub](https://hub.docker.com/). Developers can create [GitHub](https://github.com) repositories that contain multiple references to add-ons for easy sharing with the community.
|
||||
|
||||
1. [Tutorial: Making your first add-on](hassio_addon_tutorial.md)
|
||||
1. [Configuration](hassio_addon_config.md)
|
||||
1. [Communication](hassio_addon_communication.md)
|
||||
1. [Local Testing](hassio_addon_testing.md)
|
||||
1. [Publishing](hassio_addon_publishing.md)
|
||||
1. [Presentation](hassio_addon_presentation.md)
|
||||
1. [Repositories](hassio_addon_repository.md)
|
@ -0,0 +1,48 @@
|
||||
---
|
||||
title: Presenting your add-on
|
||||
id: version-0.72-hassio_addon_presentation
|
||||
original_id: hassio_addon_presentation
|
||||
---
|
||||
|
||||
If you decide to share your add-on to the public, paying attention to details is recommended. Of course, your add-on should have a proper name and description, but Hass.io also gives you some other tools to present your add-on even nicer.
|
||||
|
||||
## Adding documentation
|
||||
|
||||
Good documentation helps the consumer of your add-on to understand its usage, explains configuration options, points users in the right direction in the case they have questions or issues, and contains the license under which the add-on was published.
|
||||
|
||||
This file containing the documentation is usually referred to as the "README", which is generally published as the `README.md` file.
|
||||
|
||||
Take a look at other projects for inspiration. For example, see the `README.md` of the [Community Hass.io Add-ons: Homebridge](https://github.com/hassio-addons/addon-homebridge/blob/master/README.md) add-on.
|
||||
|
||||
In future versions of Hass.io, the `README.md` file will be displayed in the Home Assistant frontend.
|
||||
|
||||
## Add-on icon & logo
|
||||
|
||||
A picture is worth a thousand words. Therefore, your add-on can be improved by adding a proper image icon and logo. Those images are used when showing your add-on in the Home Assistant Hass.io panel and which will significantly improve the visual representation of your add-on.
|
||||
|
||||
Requirements for the logo of your add-on:
|
||||
|
||||
- The logo must be in the Portable Network Graphics format (`.png`).
|
||||
- The filename must be `logo.png`.
|
||||
- It is recommended to keep the logo size around 250x100px. You may choose to use a different size or aspect ratio as you seem fit for your add-on.
|
||||
|
||||
Requirements for the icon of your add-on:
|
||||
|
||||
- The icon must be in the Portable Network Graphics format (`.png`).
|
||||
- The filename must be `icon.png`.
|
||||
- The aspect ratio of the icon must be 1x1 (square).
|
||||
- It is recommended to use an icon size of 128x128px.
|
||||
|
||||
## Keeping a changelog
|
||||
|
||||
It is likely you are going to release newer versions of your add-on in the future. In case that happens, the users of your add-on would see an upgrade notice and probably want to know what changes were made in the latest version.
|
||||
|
||||
A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of your add-on and is generally published as the `CHANGELOG.md` file.
|
||||
|
||||
If you are in need of a guide on keeping a changelog, we would recommend checking the [keep a changelog](http://keepachangelog.com) website. They have developed a standard that is used by many opensource projects around the world.
|
||||
|
||||
In future versions of Hass.io, the `CHANGELOG.md` file will be displayed in the Home Assistant frontend.
|
||||
|
||||
## Apparmor
|
||||
|
||||
You can use own security profile for you Add-on with AppArmor. Default it is enabled and use the docker default profile. Put `apparmor.txt` file into your Add-on folder and it will load this file as primary profile. Use the config options to set the name of that profile.
|
@ -0,0 +1,57 @@
|
||||
---
|
||||
title: Publishing your add-on
|
||||
id: version-0.72-hassio_addon_publishing
|
||||
original_id: hassio_addon_publishing
|
||||
---
|
||||
|
||||
There are two different ways of publishing add-ons. One is to publish pre-build containers to Docker Hub and the other option is to have users build the containers locally on their Hass.io instance.
|
||||
|
||||
#### Pre-build containers
|
||||
|
||||
With pre-build containers, the developer is responsible for building the images for each architecture on their machine and push the results out to Docker Hub. This has a lot of advantages for the user. As a user it will only have to download the final container and be up and running once the download finishes. This makes the installation process fast and almost no chance of failure. This is the preferred method.
|
||||
|
||||
We have automated the process of building and publishing add-ons. See below for the instructions.
|
||||
|
||||
#### Locally build containers
|
||||
|
||||
Starting Hass.io 0.26, it is possible to distribute add-ons that will be built on the users machine. The advantage is that as a developer it is easy to test an idea and see if people are interested in your add-ons. This method includes installing and potentially compiling code. This means that installing such an add-on is slow and adds more wear and tear to users SD card/hard drive than the above mentioned pre-build solution. It also has a higher chance of failure if one of the dependencies of the container has changed or is no longer available.
|
||||
|
||||
Use this option when you are playing with add-ons and seeing if someone is interested in your work. Once you're an established repository, please migrate to pushing builds to Docker Hub as it greatly improves the user experience. In the future we will mark locally built add-ons in the add-on store to warn users.
|
||||
|
||||
## Build scripts to publish add-ons to Docker Hub
|
||||
|
||||
All add-ons are simple docker containers. Inside your add-on `config.json` you specify the Docker image that will be installed for your add-on:
|
||||
|
||||
```json
|
||||
{
|
||||
...
|
||||
|
||||
"image": "myhub/image-{arch}-addon-name",
|
||||
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
You can use `{arch}` inside the image name to support multiple architectures with 1 configuration file. It will be replaced with the architecture of the user when we load the image. If you use `Buildargs` you can use the `build.json` to overwrite our default args.
|
||||
|
||||
Hass.io assumes that the `master` branch of your add-on repository matches the latest tag on Docker Hub. When you're building a new version, it's suggested that you use another branch, ie `build` or do it with a PR on GitHub. After you push the add-on to [Docker Hub](https://hub.docker.com/), you can merge this branch to master.
|
||||
|
||||
## Custom Add-ons
|
||||
|
||||
You need a Docker Hub account to make your own add-ons. You can build your docker images with docker `build` command or use our script that make it simple. Pull our [builder docker engine][builder] and run one of the following commands.
|
||||
|
||||
For a git repository:
|
||||
|
||||
```bash
|
||||
$ docker run --rm --privileged -v ~/.docker:/root/.docker homeassistant/amd64-builder --all -t addon-folder -r https://github.com/xy/addons -b branchname
|
||||
```
|
||||
|
||||
For a local repository:
|
||||
|
||||
```bash
|
||||
$ docker run --rm --privileged -v ~/.docker:/root/.docker -v /my_addon:/data homeassistant/amd64-builder --all -t /data
|
||||
```
|
||||
|
||||
> If you are developing on macOS and using Docker for Mac, you may encounter an error message similar to the following: <code>error creating aufs mount to /var/lib/docker/aufs/mnt/<SOME_ID>-init: invalid argument</code>. A proposed workaround is to add the following to the Advanced Daemon JSON configuration via Docker > Preferences > Daemon > Advanced: <code>"storage-driver" : "aufs"</code>.
|
||||
|
||||
[builder]: https://github.com/home-assistant/hassio-build/tree/master/builder
|
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: Create an add-on repository
|
||||
id: version-0.72-hassio_addon_repository
|
||||
original_id: hassio_addon_repository
|
||||
---
|
||||
|
||||
An add-on repository can contain one or more add-ons. Each add-on is stored in its own unique folder. To be indentified as a repository, the repository must contain a configuration file.
|
||||
|
||||
Check the [Example add-on repository](https://github.com/home-assistant/hassio-addons-example) for further details.
|
||||
|
||||
## Installing a repository
|
||||
|
||||
A user can add a repository by going to the Hass.io panel in Home Assistant, clicking on the store icon in the top right, copy/paste the URL of your repostory into the repository textarea and click on **Save**.
|
||||
|
||||
## Repository configuration
|
||||
|
||||
Each repository is required to contain `repository.json` at the root in the git repository.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Name of repository",
|
||||
"url": "http://www.example/addons",
|
||||
"maintainer": "HomeAssistant Team <info@home-assistant.io>"
|
||||
}
|
||||
```
|
||||
|
||||
| Key | Required | Description |
|
||||
| --- | -------- | ----------- |
|
||||
| name | yes | Name of the repository
|
||||
| url | no | Homepage of the repository. Here you can explain the various add-ons.
|
||||
| maintainer | no | Contact info of the maintainer.
|
31
website/versioned_docs/version-0.72/hassio_addon_testing.md
Normal file
31
website/versioned_docs/version-0.72/hassio_addon_testing.md
Normal file
@ -0,0 +1,31 @@
|
||||
---
|
||||
title: Local add-on testing
|
||||
id: version-0.72-hassio_addon_testing
|
||||
original_id: hassio_addon_testing
|
||||
---
|
||||
|
||||
The fastest way to develop add-ons is by adding them to your local add-on repository. To access your local add-on repository, install either the [Samba add-on] or [SSH add-on].
|
||||
|
||||
Right now add-ons will work with images that are stored on Docker Hub (using `image` from add-on config). Without `image` inside local add-ons repository it to be built on the device.
|
||||
|
||||
## Local build
|
||||
|
||||
You can build and try the addon on your developer machine also. Move all addon stuff into a temp folder. If you use `FROM $BUILD_FROM` you need set a base image with build args. Normally you can use follow base images:
|
||||
|
||||
- armhf: `homeassistant/armhf-base:latest`
|
||||
- aarch64: `homeassistant/aarch64-base:latest`
|
||||
- amd64: `homeassistant/amd64-base:latest`
|
||||
- i386: `homeassistant/i386-base:latest`
|
||||
|
||||
Use `docker` to build the test addon: `docker build --build-arg BUILD_FROM="homeassistant/amd64-base:latest" -t local/my-test-addon .`
|
||||
|
||||
## Local run
|
||||
|
||||
Create a new folder for data and add a test _options.json_ file. After that you can run your add-on with: `docker run --rm -v /tmp/my_test_data:/data -p PORT_STUFF_IF_NEEDED local/my-test-addon`
|
||||
|
||||
## Logs
|
||||
|
||||
All stdout and stderr are redirected to the Docker logs. The logs can be fetched from the add-on page inside the Hass.io panel in Home Assistant.
|
||||
|
||||
[Samba add-on]: https://www.home-assistant.io/addons/samba/
|
||||
[SSH add-on]: https://www.home-assistant.io/addons/ssh/
|
179
website/versioned_docs/version-0.72/hassio_addon_tutorial.md
Normal file
179
website/versioned_docs/version-0.72/hassio_addon_tutorial.md
Normal file
@ -0,0 +1,179 @@
|
||||
---
|
||||
title: Tutorial: Making your first add-on
|
||||
id: version-0.72-hassio_addon_tutorial
|
||||
original_id: hassio_addon_tutorial
|
||||
---
|
||||
|
||||
So you've got Home Assistant going and you've been enjoying the built-in add-ons but you're missing this one application. Time to make your own add-on! In Hass.io 0.24 we introduced the option to have local add-ons be build on your device. This is great for developing new add-ons locally.
|
||||
|
||||
To get started with developing add-ons, we first need access to where Hass.io looks for local add-ons. For this you can use the Samba add-on or the SSH add-on.
|
||||
|
||||
For Samba, once you have enabled and started it, your Hass.io instance will show up in your local network tab and share a folder called "addons". This is the folder to store your custom add-ons.
|
||||
|
||||
If you are on macOS and the folder is not showing up automatically, go to Finder and press CMD+K then enter 'smb://hassio.local'
|
||||
|
||||

|
||||
|
||||
For SSH, you will have to install it. Before you can start it, you will have to have a private/public key pair and store your public key in the add-on config ([see docs for more info][ssh]). Once started, you can SSH to Hass.io and store your custom add-ons in "/addons".
|
||||
|
||||

|
||||
|
||||
Once you have located your add-on directory, it's time to get started!
|
||||
|
||||
[ssh]: https://www.home-assistant.io/addons/ssh/
|
||||
|
||||
## Step 1: The basics
|
||||
|
||||
- Create a new directory called `hello_world`
|
||||
- Inside that directory create three files.
|
||||
|
||||
`Dockerfile`:
|
||||
```
|
||||
ARG BUILD_FROM
|
||||
FROM $BUILD_FROM
|
||||
|
||||
ENV LANG C.UTF-8
|
||||
|
||||
# Copy data for add-on
|
||||
COPY run.sh /
|
||||
RUN chmod a+x /run.sh
|
||||
|
||||
CMD [ "/run.sh" ]
|
||||
```
|
||||
|
||||
`config.json`:
|
||||
```json
|
||||
{
|
||||
"name": "Hello world",
|
||||
"version": "1",
|
||||
"slug": "hello_world",
|
||||
"description": "My first real add-on!",
|
||||
"startup": "before",
|
||||
"boot": "auto",
|
||||
"options": {},
|
||||
"schema": {}
|
||||
}
|
||||
```
|
||||
|
||||
`run.sh`:
|
||||
```bash
|
||||
echo Hello world!
|
||||
```
|
||||
|
||||
## Step 2: Installing and testing your add-on
|
||||
|
||||
Now comes the fun part, time to open the Hass.io UI and install and run your add-on.
|
||||
|
||||
- Open the Home Assistant frontend
|
||||
- Go to the Hass.io panel
|
||||
- On the top right click the shopping basket to go to the add-on store.
|
||||
|
||||

|
||||
|
||||
- On the top right click the refresh button
|
||||
- You should now see a new card called "Local" that lists your add-on!
|
||||
|
||||

|
||||
|
||||
- Click on your add-on to go to the add-on details page.
|
||||
- Install your add-on
|
||||
- Start your add-on
|
||||
- Refresh the logs of your add-on, you should now see "Hello world!" in your logs.
|
||||
|
||||

|
||||
|
||||
### I don't see my add-on?!
|
||||
|
||||
Oops! You clicked refresh in the store and your add-on didn't show up. Or maybe you just updated an option, clicked refresh and saw your add-on disappear.
|
||||
|
||||
When this happens, it means that your `config.json` is invalid. It's either invalid JSON or one of the specified options is incorrect. To see what went wrong, go to the Hass.io panel and in the supervisor card click on "View logs". This should bring you to a page with the logs of the supervisor. Scroll to the bottom and you should be able to find the validation error.
|
||||
|
||||
Once you fixed the error, go to the add-on store and click refresh again.
|
||||
|
||||
## Step 3: Hosting a server
|
||||
|
||||
Until now we've been able to do some basic stuff, but it's not very useful yet. So let's take it one step further and host a server that we expose on a port. For this we're going to use the built-in HTTP server that comes with Python 3.
|
||||
|
||||
To do this, we will need to update our files as follows:
|
||||
|
||||
- `Dockerfile`: Install Python 3
|
||||
- `config.json`: Make the port from the container available on the host
|
||||
- `run.sh`: Run the Python 3 command to start the HTTP server
|
||||
|
||||
Add to your `Dockerfile` before `RUN`:
|
||||
|
||||
```
|
||||
# Install requirements for add-on
|
||||
RUN apk add --no-cache python3
|
||||
|
||||
# Python 3 HTTP Server serves the current working dir
|
||||
# So let's set it to our add-on persistent data directory.
|
||||
WORKDIR /data
|
||||
```
|
||||
|
||||
Add "ports" to `config.json`. This will make TCP on port 8000 inside the container available on the host on port 8000.
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Hello world",
|
||||
"version": "0.2",
|
||||
"slug": "hello_world",
|
||||
"description": "My first real add-on!",
|
||||
"startup": "before",
|
||||
"boot": "auto",
|
||||
"options": {},
|
||||
"schema": {},
|
||||
"ports": {
|
||||
"8000/tcp": 8000
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Update `run.sh` to start the Python 3 server:
|
||||
|
||||
```
|
||||
python3 -m http.server
|
||||
```
|
||||
|
||||
## Step 4: Installing the update
|
||||
|
||||
Since we updated the version number in our `config.json`, Home Assistant will show an update button when looking at the add-on details. You might have to refresh your browser or click the refresh button in the add-on store for it to show up. If you did not update the version number, you can also uninstall and install the add-on again. After installing the add-on again, make sure you start it.
|
||||
|
||||
Now navigate to [http://hassio.local:8000](http://hassio.local:8000) to see our server in action!
|
||||
|
||||

|
||||
|
||||
## Bonus: Working with add-on options
|
||||
|
||||
In the screenshot you've probably seen that our server only served up 1 file: `options.json`. This file contains the user configuration for this add-on. Because we specified an empty "config" and "schema" in our `config.json`, the file is currently empty.
|
||||
|
||||
Let's see if we can get some data into that file!
|
||||
|
||||
To do this, we need to specify the default options and a schema for the user to change the options.
|
||||
|
||||
Change the options and schema entries in your `config.json` with the following:
|
||||
|
||||
```json
|
||||
{
|
||||
…
|
||||
|
||||
"options": {
|
||||
"beer": true,
|
||||
"wine": true,
|
||||
"liquor": false,
|
||||
"name": "world",
|
||||
"year": 2017
|
||||
},
|
||||
"schema": {
|
||||
"beer": "bool",
|
||||
"wine": "bool",
|
||||
"liquor": "bool",
|
||||
"name": "str",
|
||||
"year": "int"
|
||||
},
|
||||
|
||||
…
|
||||
}
|
||||
```
|
||||
|
||||
Refresh the add-on store and re-install your add-on. You will now see the options available in the add-on config screen. When you now go back to our Python 3 server and download `options.json`, you'll see the options you set. [Example of how options.json can be used inside `run.sh`](https://github.com/home-assistant/hassio-addons/blob/master/mosquitto/run.sh#L4-L6)
|
45
website/versioned_docs/version-0.72/hassio_debugging.md
Normal file
45
website/versioned_docs/version-0.72/hassio_debugging.md
Normal file
@ -0,0 +1,45 @@
|
||||
---
|
||||
title: Debugging Hass.io
|
||||
id: version-0.72-hassio_debugging
|
||||
original_id: hassio_debugging
|
||||
---
|
||||
|
||||
> This section is not for users. Use the [SSH add-on] to SSH into Hass.io. This is for <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 people who are running the Hass.io image and are working on the base image. If you use the generic Linux installer script, you should be able to access your host and logs as per your host.
|
||||
|
||||
## SSH access to the host
|
||||
|
||||
Create an `authorized_keys` file containing your public key, and place it in the root of the boot partition of your SD card. Once the device is booted, you can access your device as root over SSH on port 22222.
|
||||
|
||||
Windows instructions how to generate and use private/public keys with Putty are [here][windows-keys]. Instead of the droplet instructions, add the public key as per above instructions.
|
||||
|
||||
Alternative instructions, for Mac, Windows and Linux can be found [here](https://help.github.com/articles/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent/#platform-mac).
|
||||
|
||||
Follow steps 1-4 under 'Generating a new SSH key' (The other sections are not applicable to Hass.io and can be ignored.)
|
||||
|
||||
Step 3 in the link above, shows the path to the private key file `id_rsa` for your chosen operating system. Your public key, `id_rsa.pub`, is saved in the same folder. Next, select all text from text box "Public key for pasting into OpenSSH authorized_keys file" and save it to the root of your SD card as `authorized_keys`.
|
||||
|
||||
> Make sure when you are copying the public key to the root of the /resin-boot partition of the SD card that you rename the file correctly to `authorized_keys` with no `.pub` file extension.
|
||||
|
||||
You should then be able to SSH into your Hass.io device. On mac/linux, use:
|
||||
```
|
||||
ssh root@hassio.local -p 22222
|
||||
```
|
||||
|
||||
## Checking the logs
|
||||
|
||||
```bash
|
||||
# Logs from the supervisor service on the Host OS
|
||||
journalctl -f -u resin-supervisor.service
|
||||
|
||||
# Hass.io supervisor logs
|
||||
docker logs resin_supervisor
|
||||
|
||||
# Home Assistant logs
|
||||
docker logs homeassistant
|
||||
```
|
||||
|
||||
[windows-keys]: https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-putty-on-digitalocean-droplets-windows-users
|
80
website/versioned_docs/version-0.72/hassio_hass.md
Normal file
80
website/versioned_docs/version-0.72/hassio_hass.md
Normal file
@ -0,0 +1,80 @@
|
||||
---
|
||||
title: Hass.io <> Home Assitant integration development
|
||||
sidebar_label: HASS Integration development
|
||||
id: version-0.72-hassio_hass
|
||||
original_id: hassio_hass
|
||||
---
|
||||
|
||||
These steps will help you connect your local Home Assistant to a remote Hass.io instance. You can then make changes locally to either the Hass.io component or the frontend and test it out against a real instance.
|
||||
|
||||
For this guide, we're going to assume that you have an Hass.io instance up and running. If you don't, you can use the generic installation method to install it inside a [virtual machine](https://github.com/home-assistant/hassio-build/tree/master/install#install-hassio).
|
||||
|
||||
## SSH Access
|
||||
|
||||
To develop for the frontend, we're going to need SSH access to the host machine.
|
||||
|
||||
- If you're using a standard Hass.io installation, check [these instructions](hassio_debugging.md#ssh-access-to-the-host).
|
||||
- If you're using the generic installer on a VM, setup port forwarding from the virtual machine port 22 to port 10022 on the host. You can then connect to it using `ssh your-username@127.0.0.1 -p 10022`.
|
||||
- If you're using the generic installer on your own machine, check the manual for your operating system.
|
||||
|
||||
## Getting connection details
|
||||
|
||||
To connect to a remote Hass.io from Home Assistant, we need two pieces of information: the location where the supervisor API is running and an auth token to connect to it.
|
||||
|
||||
To get these info, do the following steps:
|
||||
|
||||
- SSH into the Hass.io host machine (this is not the SSH add-on!)
|
||||
- If you're using a generic installation, run `sudo bash` to change to root.
|
||||
- Run `docker inspect homeassistant | grep HASSIO`. The output should contain a value for `HASSIO` and `HASSIO_TOKEN`. `HASSIO` should be an ip address and `HASSIO_TOKEN` is a string with random letters/numbers.
|
||||
- Disconnect the SSH session.
|
||||
|
||||
## Having Home Assistant connect to remote Hass.io
|
||||
|
||||
The connection with the supervisor is hidden inside the host and is only accessible from applications running on the host. So to make it accessible for our Home Assistant instance, we will need to route the connection to our computer running Home Assitant. We're going to do this by forwarding ports via an SSH connection.
|
||||
|
||||
We are going to SSH from our machine running Home Assistant into the remote Hass.io host. We're going to configure our SSH connection to forward all local connections to localhost port 10081 to be sent from the Hass.io host to the IP address that we got as `HASSIO` value in the last step.
|
||||
|
||||
> These instructions are for non-Windows systems
|
||||
|
||||
We can setup port forwarding from the Hass.io machine to our machine by adding the following line to the SSH command: `-L10081:<HASSIO VALUE>:80`. For example, if the value of HASSIO was `172.30.32.2` and you run Hass.io generic installer via a VM, the command would look like this:
|
||||
|
||||
```bash
|
||||
ssh paulus@127.0.0.1 -p 10022 -L10081:172.30.32.2:80
|
||||
```
|
||||
|
||||
As long as the terminal window with the SSH connection is open, the port forwarding will remain active.
|
||||
|
||||
Now let's open a new terminal window and start Home Assistant.
|
||||
|
||||
First, make sure Home Assistant will load the Hass.io component by adding `hassio:` to your `configuration.yaml` file. Next, we will need to tell Hass.io component how to connect to the remote Hass.io instance, we do this by setting the `HASSIO` and `HASSIO_TOKEN` environment variables when starting Home Assistant. Note that the `HASSIO` value is not the same as the one that we saw above.
|
||||
|
||||
```bash
|
||||
HASSIO=127.0.0.1:10081 HASSIO_TOKEN=<VALUE OF HASSIO_TOKEN> hass
|
||||
```
|
||||
|
||||
Voila. Your local Home Assistant installation will now connect to a remote Hass.io instance.
|
||||
|
||||
## Frontend development
|
||||
|
||||
> This requires Home Assistant 0.71 or later.
|
||||
|
||||
We need a couple more steps to do frontend development. First, make sure you have a Home Assitant frontend development set up ([instructions](frontend_index.md)).
|
||||
|
||||
Update the Hass.io component configuration in your `configuration.yaml` to point at the frontend repository:
|
||||
|
||||
```yaml
|
||||
# configuration.yaml
|
||||
hassio:
|
||||
development_repo: /home/paulus/dev/hass/home-assistant-polymer
|
||||
```
|
||||
|
||||
To build a local version of the Hass.io panel, go to the frontend repository and run:
|
||||
|
||||
```bash
|
||||
cd hassio
|
||||
script/build_hassio
|
||||
```
|
||||
|
||||
Now start Home Assistant as discussed in the previous section and it will now connect to the remote Hass.io but show your local frontend.
|
||||
|
||||
We're currently transitioning in how we're building the frontend so we don't have an incremental development mode just yet. For now, after making a local change, run `script/build_hassio` again.
|
79
website/versioned_docs/version-0.72/intent_builtin.md
Normal file
79
website/versioned_docs/version-0.72/intent_builtin.md
Normal file
@ -0,0 +1,79 @@
|
||||
---
|
||||
title: Built-in intents
|
||||
id: version-0.72-intent_builtin
|
||||
original_id: intent_builtin
|
||||
---
|
||||
|
||||
Home Assistant comes with a couple of built-in intents. These intents aim to offer similar functionality as exposed via the services. All built-in intents are prefixed with "Hass" to avoid collision with user defined intents.
|
||||
|
||||
## Core
|
||||
|
||||
### HassTurnOff
|
||||
|
||||
Turn an entity off.
|
||||
|
||||
| Slot name | Type | Required | Description
|
||||
| --------- | ---- | -------- | -----------
|
||||
| name | string | Yes | Name of the entity to turn off.
|
||||
|
||||
### HassTurnOn
|
||||
|
||||
Turn an entity on.
|
||||
|
||||
| Slot name | Type | Required | Description
|
||||
| --------- | ---- | -------- | -----------
|
||||
| name | string | Yes | Name of the entity to turn on.
|
||||
|
||||
### HassToggle
|
||||
|
||||
Toggle the state of an entity.
|
||||
|
||||
| Slot name | Type | Required | Description
|
||||
| --------- | ---- | -------- | -----------
|
||||
| name | string | Yes | Name of the entity to toggle.
|
||||
|
||||
## Cover
|
||||
|
||||
### HassOpenCover
|
||||
|
||||
Open a cover.
|
||||
|
||||
| Slot name | Type | Required | Description
|
||||
| --------- | ---- | -------- | -----------
|
||||
| name | string | Yes | Name of the cover entity to open.
|
||||
|
||||
### HassCloseCover
|
||||
|
||||
Close a cover.
|
||||
|
||||
| Slot name | Type | Required | Description
|
||||
| --------- | ---- | -------- | -----------
|
||||
| name | string | Yes | Name of the cover entity to close.
|
||||
|
||||
## Light
|
||||
|
||||
### HassLightSet
|
||||
|
||||
Set the state of a light.
|
||||
|
||||
| Slot name | Type | Required | Description
|
||||
| --------- | ---- | -------- | -----------
|
||||
| name | string | Yes | Name of the entity to toggle.
|
||||
| color | string, name of valid color | No | Color to change the light to.
|
||||
| brightness | integer, 0-100 | No | Brightness to change the light to.
|
||||
|
||||
## Shopping List
|
||||
|
||||
### HassShoppingListAddItem
|
||||
|
||||
Add an item to the shopping list.
|
||||
|
||||
| Slot name | Type | Required | Description
|
||||
| --------- | ---- | -------- | -----------
|
||||
| item | string | Yes | Name of item to add to the list.
|
||||
|
||||
### HassShoppingListLastItems
|
||||
|
||||
List the last 5 items on the shopping list.
|
||||
|
||||
_This intent has no slots._
|
21
website/versioned_docs/version-0.72/intent_conversation.md
Normal file
21
website/versioned_docs/version-0.72/intent_conversation.md
Normal file
@ -0,0 +1,21 @@
|
||||
---
|
||||
title: Registering sentences
|
||||
id: version-0.72-intent_conversation
|
||||
original_id: intent_conversation
|
||||
---
|
||||
|
||||
The conversation component handles incoming commands from the frontend and converts them to intents. It does this based on registered sentences.
|
||||
|
||||
As a component, you can register sentences with the conversation component to allow it to be remote controlled. Refer to named slots by putting the slot name between curly braces: `{item}`. Use square brackets around (partial) words to mark them as optional.
|
||||
|
||||
Example code:
|
||||
|
||||
```python
|
||||
async def async_setup(hass, config):
|
||||
hass.components.conversation.async_register('MyCoolIntent', [
|
||||
'I think that {object} is [very] cool',
|
||||
'Nothing is cooler than {object}'
|
||||
])
|
||||
```
|
||||
|
||||
If a sentence like "I think that beer is cool" comes in, the conversation component will generate an intent of type `MyCoolIntent` and with 1 slot, named `object` and value `beer`.
|
54
website/versioned_docs/version-0.72/intent_firing.md
Normal file
54
website/versioned_docs/version-0.72/intent_firing.md
Normal file
@ -0,0 +1,54 @@
|
||||
---
|
||||
title: Firing intents
|
||||
id: version-0.72-intent_firing
|
||||
original_id: intent_firing
|
||||
---
|
||||
|
||||
When you fire an intent, you will get a response back or an error will be raised. It is up to the component to return the result to the user.
|
||||
|
||||
Example code to handle an intent in Home Assistant.
|
||||
|
||||
```python
|
||||
from homeassistant.helpers import intent
|
||||
|
||||
intent_type = 'TurnLightOn'
|
||||
slots = {
|
||||
'entity': { 'value': 'Kitchen' }
|
||||
}
|
||||
|
||||
try:
|
||||
intent_response = yield from intent.async_handle(
|
||||
hass, 'example_component', intent_type, slots
|
||||
)
|
||||
|
||||
except intent.UnknownIntent as err:
|
||||
_LOGGER.warning('Received unknown intent %s', intent_type)
|
||||
|
||||
except intent.InvalidSlotInfo as err:
|
||||
_LOGGER.error('Received invalid slot data: %s', err)
|
||||
|
||||
except intent.IntentError:
|
||||
_LOGGER.exception('Error handling request for %s', intent_type)
|
||||
```
|
||||
|
||||
The intent response is an instance of `homeassistant.helpers.intent.IntentResponse`.
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| `intent` | Intent | Instance of intent that triggered response. |
|
||||
| `speech` | Dictionary | Speech responses. Each key is a type. Allowed types are `plain` and `ssml`. |
|
||||
| `card` | Dictionary | Card responses. Each key is a type. |
|
||||
|
||||
Speech dictionary values:
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| `speech` | String | The text to say
|
||||
| `extra_data` | Any | Extra information related to this speech.
|
||||
|
||||
Card dictionary values:
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| `title` | String | The title of the card
|
||||
| `content` | Any | The content of the card
|
44
website/versioned_docs/version-0.72/intent_handling.md
Normal file
44
website/versioned_docs/version-0.72/intent_handling.md
Normal file
@ -0,0 +1,44 @@
|
||||
---
|
||||
title: Handling intents
|
||||
id: version-0.72-intent_handling
|
||||
original_id: intent_handling
|
||||
---
|
||||
|
||||
Any component can register to handle intents. This allows a single component to handle intents fired from multiple voice assistants.
|
||||
|
||||
A component has to register an intent handler for each type that it wants to handle. Intent handlers have to extend `homeassistant.helpers.intent.IntentHandler`
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
from homeassistant.helpers import intent
|
||||
|
||||
DATA_KEY = 'example_key'
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_setup(hass, config):
|
||||
hass.data[DATA_KEY] = 0
|
||||
intent.async_register(hass, CountInvocationIntent())
|
||||
|
||||
|
||||
class CountInvocationIntent(intent.IntentHandler):
|
||||
"""Handle CountInvocationIntent intents."""
|
||||
|
||||
# Type of intent to handle
|
||||
intent_type = 'CountInvocationIntent'
|
||||
|
||||
# Optional. A validation schema for slots
|
||||
# slot_schema = {
|
||||
# 'item': cv.string
|
||||
# }
|
||||
|
||||
@asyncio.coroutine
|
||||
def async_handle(self, intent_obj):
|
||||
"""Handle the intent."""
|
||||
intent_obj.hass.data[DATA_KEY] += 1
|
||||
|
||||
response = intent_obj.create_response()
|
||||
response.async_set_speech(
|
||||
"This intent has been invoked {} times".format(
|
||||
intent_obj.hass.data[DATA_KEY]))
|
||||
return response
|
||||
```
|
36
website/versioned_docs/version-0.72/intent_index.md
Normal file
36
website/versioned_docs/version-0.72/intent_index.md
Normal file
@ -0,0 +1,36 @@
|
||||
---
|
||||
title: Intents
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-intent_index
|
||||
original_id: intent_index
|
||||
---
|
||||
|
||||
An intent is a description of a user's intention. Intents are generated by user actions, like asking Amazon Echo to turn on a light.
|
||||
|
||||
<a href='https://docs.google.com/drawings/d/1i9AsOQNCBCaeM14QwEglZizV0lZiWKHZgroZc9izB0E/edit'>
|
||||
<img
|
||||
src='/img/en/intents/overview.png'
|
||||
alt='Architectural overview of intents in Home Assistant'
|
||||
/>
|
||||
</a>
|
||||
|
||||
|
||||
Intents are fired by components that receive them from external sources/services. Conversation, Alexa, API.ai and Snips are currently sourcing intents.
|
||||
|
||||
Any component can handle intents. This makes it very easy for developers to integrate with all voice assistants at once.
|
||||
|
||||
Intents are implemented using the `homeassistant.helpers.intent.Intent` class. It contains the following properties:
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| `hass` | Home Assistant | The Home Assistant instance that fired the intent.
|
||||
| `platform` | string | The platform that fired the intent
|
||||
| `intent_type` | string | The type (name) of the intent
|
||||
| `slots` | dictionary | Contains the slot values keyed by slot name.
|
||||
| `text_input` | string | Optional. The raw text input that initiated the intent.
|
||||
|
||||
Description of the slots dictionary values.
|
||||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| Value | anything | Value of the slot.
|
@ -0,0 +1,45 @@
|
||||
---
|
||||
title: Backend Localization
|
||||
id: version-0.72-internationalization_backend_localization
|
||||
original_id: internationalization_backend_localization
|
||||
---
|
||||
|
||||
## Translation Strings
|
||||
Platform translation strings are stored as JSON in the [home-assistant](https://github.com/home-assistant/home-assistant) repository. These files must be located adjacent to the component/platform they belong to. Components must have their own directory, and the file is simply named `strings.json` in that directory. For platforms, they are named `strings.<platform name>.json` in the platform directory. This file will contain the different strings that will be translatable.
|
||||
|
||||
In order to test changes to translation files, the translation strings must be compiled into Home Assistant’s translation directories by running the following script:
|
||||
|
||||
```bash
|
||||
$ script/translations_develop
|
||||
```
|
||||
|
||||
After the pull request with the strings file is merged into the `dev` branch, the strings will be automatically uploaded to Lokalise, where contributors can submit translations. The translated strings in Lokalise will be periodically pulled in to the home-assistant repository.
|
||||
|
||||
## States Localization
|
||||
The first step when localizing platform states is to ensure that the states defined in the actual platform code are defined in `snake_case`. The states should not contain capital letters or spaces. Next, the strings file needs to be created. The states should exist under the `state` key, and map the backend state keys to their English translations. [The season sensor localization](https://github.com/home-assistant/home-assistant/pull/12453/commits/bb2f328ce10c3867990e34a88da64e2f8dc7a5c4) is a good example.
|
||||
|
||||
## Configuration Flow Localization
|
||||
The translation strings for the configuration flow handler are defined under the `config` key. An example strings file below describes the different supported keys:
|
||||
|
||||
```json
|
||||
{
|
||||
"config": {
|
||||
"title": "This title is shown in the integrations list",
|
||||
"step": {
|
||||
"init": {
|
||||
"title": "The user visible title of the `init` step.",
|
||||
"description": "Markdown that is shown with the step.",
|
||||
"data": {
|
||||
"api_key": "The label for the `api_key` input field"
|
||||
}
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"invalid_api_key": "This message will be displayed if `invalid_api_key` is returned as a flow error."
|
||||
},
|
||||
"abort": {
|
||||
"stale_api_key": "This message will be displayed if `stale_api_key` is returned as the abort reason."
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
@ -0,0 +1,14 @@
|
||||
---
|
||||
title: Custom Component Localization
|
||||
id: version-0.72-internationalization_custom_component_localization
|
||||
original_id: internationalization_custom_component_localization
|
||||
---
|
||||
|
||||
## Translation Strings
|
||||
Unlike localized strings merged in the home-assistant repository, custom components cannot take advantage of Lokalise for user submitted translations. However, custom component authors can still include translation with their components. These will be read from the `.translations` directory, adjacent to the component source file. They are named `<component/platform name>.<language_code>.json`, unless the custom component exists in its own directory, in which case the file is simply named `<language_code>.json` in the `.translations` directory.
|
||||
|
||||
These files follow the same formatting as [backend translation string files](internationalization_backend_localization.md), but a copy will exist for each translated language.
|
||||
|
||||
The language codes follow the [BCP47](https://tools.ietf.org/html/bcp47) format. The [frontend translation files](https://github.com/home-assistant/home-assistant-polymer/tree/master/translations) can also be referred to if you are unsure of the correct language code to use.
|
||||
|
||||
The frontend will serve these files after Home Assistant is restarted.
|
@ -0,0 +1,13 @@
|
||||
---
|
||||
title: Internationalization
|
||||
id: version-0.72-internationalization_index
|
||||
original_id: internationalization_index
|
||||
---
|
||||
|
||||
The Home Assistant internationalization project includes preparing platforms and the frontend for localization, as well as the actual translation of localized strings.
|
||||
|
||||
Some compmonents and platforms will have strings that need to be localized specifically for that platform. These strings are managed in the core [home-assistant](https://github.com/home-assistant/home-assistant) repository. The Home Assistant backend will serve strings to the clients based on the loaded components in the running instance.
|
||||
|
||||
There are also localizable strings that exist only on the frontend. These strings are managed in the [home-assistant-polymer](https://github.com/home-assistant/home-assistant-polymer) repository. These strings are stored with the frontend and don’t depend on the backend configuration.
|
||||
|
||||
Our strings are translated by the community using the online translation tool [Lokalise](https://lokalise.co/).
|
@ -0,0 +1,42 @@
|
||||
---
|
||||
title: Translation
|
||||
id: version-0.72-internationalization_translation
|
||||
original_id: internationalization_translation
|
||||
---
|
||||
|
||||
## How to start
|
||||
Translations for Home Assistant are managed through Lokalise, an online translation management tool. Our translations are split between two projects, a backend project for platform-specific translations, and a frontend project for UI translations. Click the links below to join both projects! Even if your language is completely translated, extra proofreading is a big help! Please feel free to review the existing translations, and vote for alternatives that might be more appropriate.
|
||||
|
||||
- [Join the frontend translation team](https://lokalise.co/signup/3420425759f6d6d241f598.13594006/all/)
|
||||
- [Join the backend translation team](https://lokalise.co/signup/130246255a974bd3b5e8a1.51616605/all/)
|
||||
|
||||
For more information about the translation workflow, please see the [Lokalise translation workflow documents](https://docs.lokalise.co/category/iOzEuQPS53-for-team-leads-and-translators).
|
||||
|
||||
> The translation of the Home Assistant frontend is still a work in progress. More phrases will be available for translation soon.
|
||||
|
||||
## Translation placeholders
|
||||
|
||||
Some translation strings will contain special placeholders that will be replaced later. Placeholders shown in square brackets `[]` are [Lokalise key references](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing). These are primarily used to link translation strings that will be duplicated. Different languages may not have the same duplicates as English, and are welcome to link duplicate translations that are not linked in English. Placeholders shown in curly brackets `{}` are [translation arguments](https://formatjs.io/guides/message-syntax/) that will be replaced with a live value when Home Assistant is running. Any translation argument placeholders present in the original string must be included in the translated string. These may include special syntax for defining plurals or other replacement rules. The linked format.js guide explains the syntax for adding plural definitions and other rules.
|
||||
|
||||
## Rules
|
||||
1. Only native speakers should submit translations.
|
||||
2. Stick to [Material Design guidelines](https://material.io/guidelines/style/writing.html).
|
||||
3. Don't translate or change proper nouns like `Home Assistant`, `Hass.io` or `Hue`.
|
||||
4. For a region specific translation, keys that will be the same as the base translation should be filled with `[VOID]`. These will be replaced during our translation build process.
|
||||
5. Translations under the `state_badge` keys will be used for the notification badge display. These translations should be short enough to fit in the badge label without overflowing. This can be tested in the Home Assistant UI either by editing the label text with your browsers development tools, or by using the States <img src='/img/dev-tools/states-icon.png' alt='states dev tool icon' class="inline" width="38" /> developer tool in the Home Assistant UI. In the UI, enter a new entity ID (`device_tracker.test`), and enter the text you want to test in state.
|
||||
6. If text will be duplicated across different translation keys, make use of the Lokalise key reference feature where possible. The base translation provides examples of this underneath the `states` translations. Please see the [Lokalise key referencing](https://docs.lokalise.co/article/KO5SZWLLsy-key-referencing) documentation for more details.
|
||||
|
||||
## Adding a new language
|
||||
If your language is not listed you can request it at [GitHub](https://github.com/home-assistant/home-assistant-polymer/issues/new). Please provide both the English name and the native name for your language. For example:
|
||||
```
|
||||
English Name: German
|
||||
Native Name: Deutsch
|
||||
```
|
||||
|
||||
> Region specific translations (`en-US`, `fr-CA`) will only be included if translations for that region need to differ from the base language translation.
|
||||
|
||||
### Maintainer steps to add a new language
|
||||
1. Language tags have to follow [BCP 47](https://tools.ietf.org/html/bcp47). A list of most language tags can be found here: [IANA sutbtag registry](http://www.iana.org/assignments/language-subtag-registry/language-subtag-registry). Examples: `fr`, `fr-CA`, `zh-Hans`. Only include the country code if country specific overrides are being included, and the base language is already translated.
|
||||
2. Add the language tag and native name in `src/translations/translationMetadata.json`. Examples: "Français", "Français (CA)"
|
||||
3. Add the new language in Lokalize.
|
||||
Note: Sometimes you have to change the tag in Lokalise (Language -> Language settings -> custom ISO code).
|
110
website/versioned_docs/version-0.72/lovelace_card_types.md
Normal file
110
website/versioned_docs/version-0.72/lovelace_card_types.md
Normal file
@ -0,0 +1,110 @@
|
||||
---
|
||||
title: Type Of Cards
|
||||
sidebar_label: Cards
|
||||
id: version-0.72-lovelace_card_types
|
||||
original_id: lovelace_card_types
|
||||
---
|
||||
|
||||
These cards are WIP and things may change.
|
||||
|
||||
## Camera preview
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| type | string | **Required** | `camera-preview`
|
||||
| entity | string | **Required** | Entity id of `camera` domain
|
||||
|
||||
## Entities
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| type | string | **Required** | `entities`
|
||||
| entities | list | **Required** | Entity id's
|
||||
| title | string | Optional | Card title
|
||||
|
||||
## Entity filter
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| type | string | **Required** | `entity-filter`
|
||||
| filter | list | **Required** | See filter description
|
||||
| card_config | object | `None` | Extra options to pass down to the card rendering the result.
|
||||
| card | string | `entities` | Card to use to render the result. Follows same rules as card type.
|
||||
|
||||
Filter options:
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| domain | string | Optional | Filter all entities that match the domain
|
||||
| state | string | Optional | Match entities that match state. Note, in YAML, make sure you wrap it in quotes to make sure it is parsed as a string.
|
||||
| entity_id | string | Optional | Filter entities by id, supports wildcards (`*living_room*`)
|
||||
|
||||
## Entity picture
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| type | string | **Required** | `entity-picture`
|
||||
| image | string | **Required** | URL of an image.
|
||||
| entity | string | **Required** | Entity id to control via picture.
|
||||
|
||||
## Glance
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| type | string | **Required** | `glance`
|
||||
| entities | list | **Required** | Entity id's
|
||||
| title | string | Optional | Card title
|
||||
|
||||
## History graph
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| type | string | **Required** | `history-graph`
|
||||
| entity | string | **Required** | Entity id of `history_graph` domain
|
||||
|
||||
## Iframe
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| type | string | **Required** | `iframe`
|
||||
| url | string | **Required** | iframe source url
|
||||
| aspect_ratio | string | `"50%"` | Iframe height-width-ratio
|
||||
| title | string | Optional | Card title
|
||||
|
||||
## Markdown
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| type | string | **Required** | `markdown`
|
||||
| content | string | **Required** | Content to render as [markdown](http://commonmark.org/help/).
|
||||
| title | string | Optional | Card title
|
||||
|
||||
## Media controller
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| type | string | **Required** | `media-control`
|
||||
| entity | string | **Required** | Entity id of `media_player` domain
|
||||
|
||||
## Picture glance
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| type | string | **Required** | `picture-glance`
|
||||
| image | string | **Required** | URL of an image.
|
||||
| entities | list | **Required** | Entity id's
|
||||
| title | string | Optional | Card title
|
||||
|
||||
## Plant info
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| type | string | **Required** | `plant-status`
|
||||
| entity | string | **Required** | Entity id of `plant` domain
|
||||
|
||||
## Weather forecast
|
||||
|
||||
| Name | Type | Default | Description
|
||||
| ---- | ---- | ------- | -----------
|
||||
| type | string | **Required** | `weather-forecast`
|
||||
| entity | string | **Required** | Entity id of `weather` domain
|
168
website/versioned_docs/version-0.72/lovelace_custom_card.md
Normal file
168
website/versioned_docs/version-0.72/lovelace_custom_card.md
Normal file
@ -0,0 +1,168 @@
|
||||
---
|
||||
title: Custom Cards
|
||||
id: version-0.72-lovelace_custom_card
|
||||
original_id: lovelace_custom_card
|
||||
---
|
||||
|
||||
You're not just limited to the cards that we decided to include in the Lovelace UI. You can build and use your own!
|
||||
|
||||
## API
|
||||
|
||||
- You define your custom card as a [custom element](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). It's up to you to decide how to render your DOM inside your element. You can use Polymer, Angular, Preact or any other popular framework (except for React – more info [here](https://custom-elements-everywhere.com/)).
|
||||
- Home Assistant will set the `config` property when the configuration changes (rare).
|
||||
- Home Assistant will set the `hass` property when the state of Home Assistant changes (frequent). Whenever the state changes, the component will have to update itself to represent the latest state.
|
||||
- Home Assistant will call `getCardSize()` to request the size of the card. Size of the card is used for the automatic distribution of cards across columns. Both `config` and `hass` properties will be available. Defaults to `1` if function is not defined.
|
||||
|
||||
## Defining your card
|
||||
|
||||
Create a new file in your Home Assistant config dir as `<config>/www/content-card-example.js` and put in the following contents:
|
||||
|
||||
```js
|
||||
class ContentCardExample extends HTMLElement {
|
||||
set hass(hass) {
|
||||
if (!this.content) {
|
||||
const card = document.createElement('ha-card');
|
||||
card.header = 'Example card';
|
||||
this.content = document.createElement('div');
|
||||
this.content.style.padding = '0 16px 16px';
|
||||
card.appendChild(this.content);
|
||||
this.appendChild(card);
|
||||
}
|
||||
|
||||
const entityId = this.config.entity;
|
||||
const state = hass.states[entityId];
|
||||
const stateStr = state ? state.state : 'unavailable';
|
||||
|
||||
this.content.innerHTML = `
|
||||
The state of ${entityId} is ${stateStr}!
|
||||
<br><br>
|
||||
<img src="http://via.placeholder.com/350x150">
|
||||
`;
|
||||
}
|
||||
|
||||
// The height of your card. Home Assistant uses this to automatically
|
||||
// distribute all cards over the available columns.
|
||||
getCardSize() {
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
|
||||
customElements.define('content-card-example', ContentCardExample);
|
||||
```
|
||||
|
||||
## Referencing your new card
|
||||
|
||||
In our example card we defined a card with the tag `content-card-example` (see last line), so our card type will be `custom:content-card-example`. And because you created the file in your `<config>/www` directory, it will be accessible in your browser via the url `/local/`.
|
||||
|
||||
```yaml
|
||||
# Example ui-lovelace.yaml
|
||||
resources:
|
||||
- url: /local/content-card-example.js
|
||||
type: js
|
||||
views:
|
||||
- name: Example
|
||||
cards:
|
||||
- type: "custom:custom-card-example"
|
||||
entity: input_boolean.switch_tv
|
||||
```
|
||||
|
||||
## Advanced example
|
||||
|
||||
Resources to load in Lovelace can be imported as a JS script, an HTML import or as a JS module import. Below is an example of a custom card using JS modules that does all the fancy things.
|
||||
|
||||
Create a new file in your Home Assistant config dir as `<config>/www/wired-cards.js` and put in the following contents:
|
||||
|
||||
```js
|
||||
import 'https://unpkg.com/wired-card@0.6.5/wired-card.js?module';
|
||||
import 'https://unpkg.com/wired-toggle@0.6.5/wired-toggle.js?module';
|
||||
import {
|
||||
LitElement, html
|
||||
} from 'https://unpkg.com/@polymer/lit-element@^0.5.2/lit-element.js?module';
|
||||
|
||||
function loadCSS(url) {
|
||||
const link = document.createElement('link');
|
||||
link.type = 'text/css';
|
||||
link.rel = 'stylesheet';
|
||||
link.href = url;
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
|
||||
loadCSS('https://fonts.googleapis.com/css?family=Gloria+Hallelujah');
|
||||
|
||||
class WiredToggleCard extends LitElement {
|
||||
static get properties() {
|
||||
return {
|
||||
hass: Object,
|
||||
config: Object,
|
||||
}
|
||||
}
|
||||
|
||||
_render({ hass, config }) {
|
||||
return html`
|
||||
<style>
|
||||
:host {
|
||||
font-family: 'Gloria Hallelujah', cursive;
|
||||
}
|
||||
wired-card {
|
||||
background-color: white;
|
||||
padding: 16px;
|
||||
display: block;
|
||||
font-size: 18px;
|
||||
}
|
||||
.state {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 8px;
|
||||
align-items: center;
|
||||
}
|
||||
wired-toggle {
|
||||
margin-left: 8px;
|
||||
}
|
||||
</style>
|
||||
<wired-card elevation="2">
|
||||
${config.entities.map(ent => hass.states[ent]).map((state) =>
|
||||
html`
|
||||
<div class='state'>
|
||||
${state.attributes.friendly_name}
|
||||
<wired-toggle
|
||||
checked="${state.state === 'on'}"
|
||||
on-change="${ev => this._toggle(state)}"
|
||||
></wired-toggle>
|
||||
</div>
|
||||
`
|
||||
)}
|
||||
</wired-card>
|
||||
`;
|
||||
}
|
||||
|
||||
_toggle(state) {
|
||||
this.hass.callService('homeassistant', 'toggle', {
|
||||
entity_id: state.entity_id
|
||||
});
|
||||
}
|
||||
|
||||
// The height of your card. Home Assistant uses this to automatically
|
||||
// distribute all cards over the available columns.
|
||||
getCardSize() {
|
||||
return this.config.entities.length + 1;
|
||||
}
|
||||
}
|
||||
customElements.define('wired-toggle-card', WiredToggleCard);
|
||||
```
|
||||
|
||||
And for your configuration:
|
||||
|
||||
```yaml
|
||||
# Example ui-lovelace.yaml
|
||||
resources:
|
||||
- url: /local/wired-cards.js
|
||||
type: module
|
||||
views:
|
||||
- name: Example
|
||||
cards:
|
||||
- type: "custom:wired-toggle-card"
|
||||
entities:
|
||||
- input_boolean.switch_ac_kitchen
|
||||
- input_boolean.switch_ac_livingroom
|
||||
- input_boolean.switch_tv
|
||||
```
|
101
website/versioned_docs/version-0.72/lovelace_index.md
Normal file
101
website/versioned_docs/version-0.72/lovelace_index.md
Normal file
@ -0,0 +1,101 @@
|
||||
---
|
||||
title: Lovelace UI
|
||||
sidebar_label: Introduction
|
||||
id: version-0.72-lovelace_index
|
||||
original_id: lovelace_index
|
||||
---
|
||||
|
||||
> This is an experimental feature. Configuration might change in future versions.
|
||||
|
||||
Starting with Home Assistant 0.72, we're experimenting with a new way of defining your interface. We're calling it the Lovelace UI.
|
||||
|
||||
The Lovelace UI is:
|
||||
|
||||
- **Extremely fast**. We create the user interface when the UI configuration changes. When a state changes, we just make the UI represent the current state.
|
||||
- **Extremely customizable**. We have a new file for just configuration. In the past, we declined UI specific options because they did not fit in the state machine. They will fit in a configuration file for a user interface.
|
||||
- **Extremely extensible**. It's based on the web standard [custom elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements). Don't like the built-in cards? Make your own! Custom cards are treated the same as built-in cards and are configured the same way. [Check the docs.](lovelace_custom_card.md)
|
||||
- **Making the backend faster**. With Lovelace, the backend will no longer need to maintain entities like groups for the sole purpose of showing them on the frontend.
|
||||
|
||||
## How it works
|
||||
|
||||
The old user interface relied solely on the state machine. This caused trouble as it meant that the state machine was now not only the source for device states, but also for user interface configuration. With Lovelace, we're taking a completely different approach. All user interface configuration will live in a seperate file, controlled by the user.
|
||||
|
||||

|
||||
|
||||
<!-- source: https://docs.google.com/drawings/d/1O1o7-wRlnsU1lLgfdtn3s46P5StJjSL5to5RU9SV8zs/edit?usp=sharing -->
|
||||
|
||||
## Trying it out
|
||||
|
||||
Create a new file `<config>/ui-lovelace.yaml` and add the following content:
|
||||
|
||||
```yaml
|
||||
name: My Awesome Home
|
||||
views:
|
||||
# The name of a view will be used as tab title.
|
||||
# Might be used for other things in the future.
|
||||
- name: Example
|
||||
# Each view can have a different theme applied. Theme should be defined in the frontend.
|
||||
theme: dark-mode
|
||||
# The cards to show on this view.
|
||||
cards:
|
||||
# The entities card will take a list of entities and show their state.
|
||||
- type: entities
|
||||
# Title of the entities card
|
||||
title: Example
|
||||
# The entities here will be shown in the same order as specified.
|
||||
entities:
|
||||
- input_boolean.switch_ac_kitchen
|
||||
- input_boolean.switch_ac_livingroom
|
||||
- input_boolean.switch_tv
|
||||
|
||||
# The filter card will filter available entities for certain criteria
|
||||
# and render it as type 'entities'.
|
||||
- type: entity-filter
|
||||
# Filter criteria. They are all optional.
|
||||
filter:
|
||||
- domain: input_boolean
|
||||
state: 'on'
|
||||
# This config will be passed to the card rendering the filter results
|
||||
card_config:
|
||||
title: Input booleans that are on
|
||||
|
||||
# Specify a tab_icon if you want the view tab to be an icon.
|
||||
- tab_icon: mdi:home-assistant
|
||||
# Name of the view. Will be used as the tooltip for tab icon
|
||||
name: Second view
|
||||
cards:
|
||||
- type: entities
|
||||
title: Lots of Kitchen AC
|
||||
entities:
|
||||
# It is totally possible to render duplicates.
|
||||
- input_boolean.switch_ac_kitchen
|
||||
- input_boolean.switch_ac_kitchen
|
||||
- input_boolean.switch_ac_kitchen
|
||||
- input_boolean.switch_ac_kitchen
|
||||
- input_boolean.switch_ac_kitchen
|
||||
- input_boolean.switch_ac_kitchen
|
||||
```
|
||||
|
||||
Add to your `configuration.yaml`:
|
||||
|
||||
```yaml
|
||||
input_boolean:
|
||||
switch_ac_kitchen:
|
||||
name: AC kitchen
|
||||
switch_ac_livingroom:
|
||||
name: AC living room
|
||||
switch_tv:
|
||||
name: TV
|
||||
```
|
||||
|
||||
Now restart Home Assistant, navigate to `<YOUR HASS URL>/lovelace`. When you make changes to `ui-lovelace.yaml`, you don't have to restart Home Assistant or refresh the page. Just hit the refresh button at the top of the UI.
|
||||
|
||||
## Current limitations
|
||||
|
||||
This is the very very early version aimed at gathering feedback. Discussion and suggestions are welcome in the [ui-schema repository](https://github.com/home-assistant/ui-schema).
|
||||
|
||||
## Change log
|
||||
|
||||
**Home Assistant 0.72**
|
||||
|
||||
- Initial release of the Lovelace UI.
|
47
website/versioned_docs/version-0.72/maintenance.md
Normal file
47
website/versioned_docs/version-0.72/maintenance.md
Normal file
@ -0,0 +1,47 @@
|
||||
---
|
||||
title: Maintenance
|
||||
id: version-0.72-maintenance
|
||||
original_id: maintenance
|
||||
---
|
||||
|
||||
This page documents a couple of points for maintaining the Home Assistant code. Most of the tasks don't need to be performed on a regular base thus the steps, used tools, or details are preserved here.
|
||||
|
||||
## Source code
|
||||
|
||||
### Line separator
|
||||
|
||||
People are using various operating systems to develop components and platforms for Home Assistant. This could lead to different line endings on file. We prefer `LN`. Especially Microsoft Windows tools tend to use `CRLF`.
|
||||
|
||||
```bash
|
||||
$ find homeassistant -name "*.py" -exec file {} \; | grep BOM
|
||||
$ find homeassistant -name "*.py" -exec file {} \; | grep CRLF
|
||||
```
|
||||
|
||||
To fix the line separator, use `dos2unix` or `sed`.
|
||||
|
||||
```bash
|
||||
$ dos2unix homeassistant/components/notify/kodi.py
|
||||
```
|
||||
|
||||
### File permissions
|
||||
|
||||
Most files don't need to the be executable. `0644` is fine.
|
||||
|
||||
### Dependencies
|
||||
|
||||
A lot of components and platforms depends on third-party Python modules. The dependencies which are stored in the `requirements_*.txt` files are tracked by [gemnasium](https://gemnasium.com/github.com/home-assistant/home-assistant) and [Requires.io](https://requires.io/github/home-assistant/home-assistant/requirements/?branch=dev).
|
||||
|
||||
If you update the requirements of a component/platform through the `REQUIREMENTS = ['modules-xyz==0.3']` entry, run the provided script to update the `requirements_*.txt` file(s).
|
||||
|
||||
```bash
|
||||
$ script/gen_requirements_all.py
|
||||
```
|
||||
|
||||
Start a test run of Home Assistant. If that was successful, include all files in a Pull Request. Add a short summary of the changes, a sample configuration entry, details about the tests you performed to ensure the update works, and other useful information to the description.
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
- Merge `current` into `next` on a regular base.
|
||||
- Optimize the images.
|
||||
|
7
website/versioned_docs/version-0.72/misc.md
Normal file
7
website/versioned_docs/version-0.72/misc.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
title: Miscellaneous
|
||||
id: version-0.72-misc
|
||||
original_id: misc
|
||||
---
|
||||
|
||||
Catch all category. Topics are not related to one another.
|
69
website/versioned_docs/version-0.72/releasing.md
Normal file
69
website/versioned_docs/version-0.72/releasing.md
Normal file
@ -0,0 +1,69 @@
|
||||
---
|
||||
title: Releasing
|
||||
id: version-0.72-releasing
|
||||
original_id: releasing
|
||||
---
|
||||
|
||||
This page describes the steps for publishing a new Home Assistant release. Those steps requires that you don't use forks but work with the repositories themself. The [hass-release](https://github.com/home-assistant/hass-release) script is a helper to do a release.
|
||||
|
||||
### Release preparation (3 days before release)
|
||||
|
||||
### GitHub
|
||||
|
||||
1. Merge `master` into `dev` to make the PR mergeable.
|
||||
1. Cut a release branch from `dev`. Example name `release-0-57`.
|
||||
1. Create a pull request from the release branch to `master` with the upcoming release number as the title.
|
||||
1. Update `homeassistant/const.py` with the correct version number (remove the `dev` tag) and push that commit to release branch.
|
||||
|
||||
### Website
|
||||
|
||||
1. Merge `current` into `next`
|
||||
1. Cut release branch of `next`. For example `release-0-57`.
|
||||
1. Open a PR from release branch to `current` with the upcoming release number as the title.
|
||||
|
||||
## Release day
|
||||
|
||||
From creating the release branch till it has been merged, we tag bugfixes with the milestone for the release (create if doesn't exist).
|
||||
|
||||
### GitHub
|
||||
|
||||
1. Cherry-pick the milestoned PRs that need to get into the release `python3 -m hassrelease milestone_cherry_pick 0.57`
|
||||
1. Run `python3 -m hassrelease release_notes 0.56` for the release notes.
|
||||
1. Once the release notes has been generated, issue `python3 -m hassrelease milestone_close 0.56`
|
||||
1. Merge pull request (DO NOT SQUASH!). Use `Merge pull request`.
|
||||
1. Go to [releases](https://github.com/home-assistant/home-assistant/releases), click `Draft a new release` and tag a new release on the `master` branch. "Tag version" and "Release title" are the version number (`O.x` for major version, `0.x.y` for minor and bug fix releases). Release description is the text from PR. Press "Publish release" to finish the process.
|
||||
1. Merge `master` into `dev`.
|
||||
1. Update `homeassistant/const.py` with the upcoming version number (including the `dev` tag) and push that commit to the `dev` branch.
|
||||
|
||||
### Website
|
||||
|
||||
1. Create a blog post in the release branch and base it on the text of the PR in the main repository. Add images, additional text, links, etc. if it adds value. Tag each platform/component in a message to documentation.
|
||||
1. Create missing documentation as stubs.
|
||||
1. Run `credits_generator`.
|
||||
1. Update `_config.yml` with a link to the new release blog post and version number (at the bottom of the file).
|
||||
1. Merge `current` into release branch (`$ git checkout release-0-40 && git merge current`) to make the PR mergeable.
|
||||
1. Merge pull request (blog post, updated frontpage, and all new documentation) to `current`. DO NOT SQUASH!
|
||||
1. Merge `current` into `next`.
|
||||
|
||||
### Docker Hub
|
||||
|
||||
Tags on Docker hub are automatically created when a release has been created on GitHub.
|
||||
|
||||
### Python Package Index
|
||||
|
||||
Checkout the `master` branch and run `script/release` to publish the new release on [Python Package Index](https://pypi.python.org).
|
||||
|
||||
### Social media
|
||||
|
||||
1. Use [hootsuite](https://hootsuite.com/dashboard) to publish a link to the release post on social media.
|
||||
|
||||
## Bugfix Release
|
||||
|
||||
1. Checkout `master` and update it. `git checkout master && git pull --rebase`
|
||||
1. Create a new release branch from `master`. `git checkout -b release-0-56-2`
|
||||
1. Cherry-pick the PRs which were milestoned.
|
||||
1. Update `homeassistant/const.py` with the correct version number (increment `PATCH_VERSION`) and push that commit to release branch.
|
||||
1. Create a pull request from the release branch to `master` with the upcoming release number as the title.
|
||||
1. Merge pull request (DO NOT SQUASH!). Use `Merge pull request`.
|
||||
1. Go to [releases](https://github.com/home-assistant/home-assistant/releases), click `Draft a new release` and tag a new release on the `master` branch. "Tag version" and "Release title" are the version number (`O.x` for major version, `0.x.y` for minor and bug fix releases). Release description is the text from PR. Press "Publish release" to finish the process.
|
||||
1. Publish the new release on PyPI.
|
150
website/versioned_sidebars/version-0.72-sidebars.json
Normal file
150
website/versioned_sidebars/version-0.72-sidebars.json
Normal file
@ -0,0 +1,150 @@
|
||||
{
|
||||
"version-0.72-Architecture": {
|
||||
"Architecture": [
|
||||
"version-0.72-architecture_index",
|
||||
"version-0.72-architecture_components",
|
||||
"version-0.72-architecture_entities",
|
||||
"version-0.72-architecture_hassio"
|
||||
],
|
||||
"Entities": [
|
||||
"version-0.72-entity_index",
|
||||
"version-0.72-entity_alarm_control_panel",
|
||||
"version-0.72-entity_binary_sensor",
|
||||
"version-0.72-entity_climate",
|
||||
"version-0.72-entity_cover",
|
||||
"version-0.72-entity_fan",
|
||||
"version-0.72-entity_light",
|
||||
"version-0.72-entity_lock",
|
||||
"version-0.72-entity_media_player",
|
||||
"version-0.72-entity_remote",
|
||||
"version-0.72-entity_sensor",
|
||||
"version-0.72-entity_switch",
|
||||
"version-0.72-entity_vacuum",
|
||||
"version-0.72-entity_weather"
|
||||
],
|
||||
"Authentication": [
|
||||
"version-0.72-auth_index",
|
||||
"version-0.72-auth_api",
|
||||
"version-0.72-auth_auth_provider"
|
||||
],
|
||||
"Configuration.yaml": [
|
||||
"version-0.72-configuration_yaml_index"
|
||||
],
|
||||
"Config Entries": [
|
||||
"version-0.72-config_entries_index",
|
||||
"version-0.72-config_entries_config_flow_handler"
|
||||
],
|
||||
"Data Entry Flow": [
|
||||
"version-0.72-data_entry_flow_index"
|
||||
],
|
||||
"Entity Registry": [
|
||||
"version-0.72-entity_registry_index"
|
||||
]
|
||||
},
|
||||
"version-0.72-Extending Frontend": {
|
||||
"Frontend": [
|
||||
"version-0.72-frontend_index",
|
||||
"version-0.72-frontend_architecture",
|
||||
"version-0.72-frontend_development"
|
||||
],
|
||||
"Extending the frontend": [
|
||||
"version-0.72-frontend_add_card",
|
||||
"version-0.72-frontend_add_more_info",
|
||||
"version-0.72-frontend_add_websocket_api"
|
||||
],
|
||||
"Custom UI": [
|
||||
"version-0.72-frontend_creating_custom_ui",
|
||||
"version-0.72-frontend_creating_custom_panels"
|
||||
],
|
||||
"Lovelace UI": [
|
||||
"version-0.72-lovelace_index",
|
||||
"version-0.72-lovelace_card_types",
|
||||
"version-0.72-lovelace_custom_card"
|
||||
]
|
||||
},
|
||||
"version-0.72-Extending HASS": {
|
||||
"Developing a feature": [
|
||||
"version-0.72-development_index",
|
||||
"version-0.72-development_environment",
|
||||
"version-0.72-development_submitting",
|
||||
"version-0.72-development_checklist",
|
||||
"version-0.72-development_guidelines",
|
||||
"version-0.72-development_testing",
|
||||
"version-0.72-development_catching_up",
|
||||
"version-0.72-development_validation",
|
||||
"version-0.72-development_typing"
|
||||
],
|
||||
"Development 101": [
|
||||
"version-0.72-dev_101_index",
|
||||
"version-0.72-dev_101_hass",
|
||||
"version-0.72-dev_101_events",
|
||||
"version-0.72-dev_101_states",
|
||||
"version-0.72-dev_101_services",
|
||||
"version-0.72-dev_101_config"
|
||||
],
|
||||
"Creating Platforms": [
|
||||
"version-0.72-creating_platform_index",
|
||||
"version-0.72-creating_platform_code_review",
|
||||
"version-0.72-creating_platform_example_light",
|
||||
"version-0.72-creating_platform_example_sensor"
|
||||
],
|
||||
"Creating Components": [
|
||||
"version-0.72-creating_component_index",
|
||||
"version-0.72-creating_component_code_review",
|
||||
"version-0.72-creating_component_deps_and_reqs",
|
||||
"version-0.72-creating_component_events",
|
||||
"version-0.72-creating_component_states",
|
||||
"version-0.72-creating_component_discovery",
|
||||
"version-0.72-creating_component_loading",
|
||||
"version-0.72-creating_component_generic_discovery"
|
||||
]
|
||||
},
|
||||
"version-0.72-Misc": {
|
||||
"Introduction": [
|
||||
"version-0.72-misc"
|
||||
],
|
||||
"External API": [
|
||||
"version-0.72-external_api_rest",
|
||||
"version-0.72-external_api_rest_python",
|
||||
"version-0.72-external_api_websocket",
|
||||
"version-0.72-external_api_server_sent_events"
|
||||
],
|
||||
"Internationalization": [
|
||||
"version-0.72-internationalization_index",
|
||||
"version-0.72-internationalization_backend_localization",
|
||||
"version-0.72-internationalization_custom_component_localization",
|
||||
"version-0.72-internationalization_translation"
|
||||
],
|
||||
"Intents": [
|
||||
"version-0.72-intent_index",
|
||||
"version-0.72-intent_firing",
|
||||
"version-0.72-intent_handling",
|
||||
"version-0.72-intent_conversation",
|
||||
"version-0.72-intent_builtin"
|
||||
],
|
||||
"asyncio": [
|
||||
"version-0.72-asyncio_index",
|
||||
"version-0.72-asyncio_101",
|
||||
"version-0.72-asyncio_categorizing_functions",
|
||||
"version-0.72-asyncio_working_with_async"
|
||||
],
|
||||
"Hass.io": [
|
||||
"version-0.72-hassio_debugging",
|
||||
"version-0.72-hassio_hass"
|
||||
],
|
||||
"Hass.io Add-Ons": [
|
||||
"version-0.72-hassio_addon_index",
|
||||
"version-0.72-hassio_addon_tutorial",
|
||||
"version-0.72-hassio_addon_config",
|
||||
"version-0.72-hassio_addon_communication",
|
||||
"version-0.72-hassio_addon_testing",
|
||||
"version-0.72-hassio_addon_publishing",
|
||||
"version-0.72-hassio_addon_presentation",
|
||||
"version-0.72-hassio_addon_repository"
|
||||
],
|
||||
"Maintainer docs": [
|
||||
"version-0.72-maintenance",
|
||||
"version-0.72-releasing"
|
||||
]
|
||||
}
|
||||
}
|
3
website/versions.json
Normal file
3
website/versions.json
Normal file
@ -0,0 +1,3 @@
|
||||
[
|
||||
"0.72"
|
||||
]
|
Loading…
x
Reference in New Issue
Block a user