This commit is contained in:
Fabian Affolter 2018-12-01 23:44:01 +01:00 committed by GitHub
parent 1d237ac1a9
commit 62751b5a5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 730 additions and 0 deletions

View File

@ -0,0 +1,12 @@
---
title: Native App Integration
sidebar_label: Introduction
id: version-0.83.0-app_integration_index
original_id: app_integration_index
---
This guide describes how to build a native Home Assistant app that communicates with Home Assistant and offers a seamless integration. Below is a list of the things that we will discuss in this guide.
- Allow the user to establish a connection and authenticate with their own Home Assistant instance.
- Send location and device info back to Home Assistant.
- A view to control the house via an authenticated webview.

View File

@ -0,0 +1,59 @@
---
title: Sending data home
id: version-0.83.0-app_integration_sending_data
original_id: app_integration_sending_data
---
There are different APIs that your app can use to send data back or communicate with Home Assistant.
## Short note on instance URLs
Some users have configured Home Assistant to be available outside of their home network using a dynamic DNS service. There are some routers that don't support hairpinning / NAT loopback: a device sending data from inside the routers network, via the externally configured DNS service, to Home Asisstant, which also resides inside the local network.
To work around this, the app will need to record which WiFi is the home network, and use a direct connection when connected to the home WiFi network.
## Webhooks
Any component in Home Assistant can register webhook endpoints. The webhook endpoints contain a randomized URL-segment which are bound to just a single update handler. Because of this, the call requires no authentication, making calls have little overhead.
Webhooks are ideal for sending quick updates, like location or battery, from your app to Home Assistant.
Webhooks are available on the local instance on `/api/webhook/<webhook id>`, which requires a direct connection. If the Home Assistant instance is configured to use Home Assistant Cloud, it is possible to get a cloud url for the webhook. This url is accessible from anywhere on the internet.
To register a webhook in your component:
```python
async def handle_webhook(hass, webhook_id, request):
"""Handle webhook callback."""
body = await request.json()
# Do something with the data
webhook_id = hass.components.webhook.async_generate_id()
hass.components.webhook.async_register(
DOMAIN, 'Name of the webhook', webhook_id, handle_webhook)
print(
"Webhook available on:",
hass.components.webhook.async_generate_url(webhook_id)
)
```
## Websocket API
With a websocket connection you will be able to stream updates from Home Assistant and control most of the things inside Home Assistant. This API is perfect if you want to show a realtime view of the house and allow the user to interact with it.
Websocket API requires authentication via an access token and a direct connection with the instance.
- [Websocket API Docs](external_api_websocket)
- [Making authenticated requests](auth_api#making-authenticated-requests)
## Rest API
With the Rest API you are able to query the state of the house and call services. Your component is also able to register new HTTP views to offer other Rest API endpoints.
Rest API requires authentication via an access token and a direct connection with the instance.
- [Rest API Docs](external_api_rest)
- [Making authenticated requests](auth_api#making-authenticated-requests)

View File

@ -0,0 +1,40 @@
---
title: Connecting to an instance
id: version-0.83.0-app_integration_setup
original_id: app_integration_setup
---
When a user first opens the app, they will need to connect to their local instance to authenticate and register the device.
## Authenticating the user
The local instance can be discovered if Home Assistant has the [zeroconf component] configured. If not configured, the user will need to be asked for the local address of their instance.
When the address of the instance is known, the app will ask the user to authenticate via [OAuth2 with Home Assistant]. Home Assistant uses IndieAuth, which means that to be able to redirect to a url that triggers your app, you need to take some extra steps. Make sure to read the last paragraph of the "Clients" section thoroughly.
## Registering the device
Once you have tokens to authenticate as a user, it's time to register the app with the app component in Home Assistant. Each native app will need to build their own support layer for their app. The setup of your component will need to use a config flow so that it is configurable via the user interface and can access advanced Home Assistant features like the device registry.
Let's take as an example that we're building an iOS application and that it is supported by the `ios` component in Home Assistant. If the component is loaded, it will register a new API endpoint on `/api/ios/register` (requiring authentication). The app can post to this endpoint to register the users' device with Home Assistant. Example payload:
```json
{
"device_type": "iPhone 6",
"firmware": "zxcx"
}
```
The endpoint will register the device with Home Assistant:
- Generate a unique webhook endpoint that the app can use to send data back to Home Assistant.
- Use the storage helper to store data.
- Register the iOS device with the [device registry](device_registry_index).
- Make the device available as a notification target.
> The following section is not implemented yet.
If the app receives a 404 HTTP status code when trying to register the device, it means the `ios` component is not loaded. In this case, the app can load the `ios` component by posting to `/api/config_entry_discovery`. This will trigger the `http_discovery` step of the config flow for the `ios` component and it will be loaded. The app can now retry the device registration.
[zeroconf component]: https://www.home-assistant.io/components/zeroconf
[OAuth2 with Home Assistant]: auth_api

View File

@ -0,0 +1,11 @@
---
title: Authenticated Webview
id: version-0.83.0-app_integration_webview
original_id: app_integration_webview
---
Your application already asked the user to authenticate. This means that your app should not ask the user to authenticate again when they open the Home Assistant UI.
To make this possible, the Home Assistant UI supports [external authentication](frontend_external_auth). This allows your app to provide hooks so that the frontend will ask your app for access tokens.
Note that this feature requires a direct connection to the instance.

View File

@ -0,0 +1,257 @@
---
title: Authentication API
sidebar_label: API
id: version-0.83.0-auth_api
original_id: auth_api
---
This page will describe the steps required for your application to authorize against and integrate with Home Assistant instances. [See a demo](https://hass-auth-demo.glitch.me) powered by our helper lib [home-assistant-js-websocket](https://github.com/home-assistant/home-assistant-js-websocket).
Each user has their own instance of Home Assistant which gives each user control over their own data. However, we also wanted to make it easy for third party developers to create applications that allow users to integrate with Home Assistant. To achieve this, we have adopted the [OAuth 2 specification][oauth2-spec] combined with the [OAuth 2 IndieAuth extension][indieauth-spec] for generating clients.
## Clients
Before you can ask the user to authorize their instance with your application, you will need a client. In traditional OAuth2, the server needs to generate a client before a user can authorize. However, as each server belongs to a user, we've adopted a slightly different approach from [IndieAuth][indieauth-clients].
The client ID you need to use is the website of your application. The redirect url has to be of the same host and port as the client ID. For example:
- client id: `https://www.my-application.io`
- redirect uri: `https://www.my-application.io/hass/auth_callback`
If you require a different redirect url (ie, if building a native app), you can add an HTML tag to the content of the website of your application (the client ID) with an approved redirect url. For example, add this to your site to whitelist redirect uri `hass://auth`:
```html
<link rel='redirect_uri' href='hass://auth'>
```
Home Assistant will scan the first 10kB of a website for link tags.
## Authorize
[![Authorization flow sequence diagram](/img/en/auth/authorize_flow.png)](https://www.websequencediagrams.com/?lz=dGl0bGUgQXV0aG9yaXphdGlvbiBGbG93CgpVc2VyIC0-IENsaWVudDogTG9nIGludG8gSG9tZSBBc3Npc3RhbnQKABoGIC0-IFVzZXI6AEMJZSB1cmwgAD4JACgOOiBHbyB0bwAeBWFuZCBhAC0ICgBQDgB1DACBFw5jb2RlAHELAE4RZXQgdG9rZW5zIGZvcgAoBgBBGlQAJQUK&s=qsd)
> All example URLs here are shown with extra spaces and new lines for display purposes only.
The authorize url should contain `client_id` and `redirect_uri` as query parameters.
```
http://your-instance.com/auth/authorize?
client_id=https%3A%2F%2Fhass-auth-demo.glitch.me&
redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2F%3Fauth_callback%3D1
```
Optionally you can also include a `state` parameter, this will be added to the redirect uri. The state is perfect to store the instance url that you are authenticating with. Example:
```
http://your-instance.com/auth/authorize?
client_id=https%3A%2F%2Fhass-auth-demo.glitch.me&
redirect_uri=https%3A%2F%2Fhass-auth-demo.glitch.me%2Fauth_callback&
state=http%3A%2F%2Fhassio.local%3A8123
```
The user will navigate to this link and be presented with instructions to log in and authorize your application. Once authorized, the user will be redirected back to the passed in redirect uri with the authorization code and state as part of the query parameters. Example:
```
https://hass-auth-demo.glitch.me/auth_callback
code=12345&
state=http%3A%2F%2Fhassio.local%3A8123
```
This authorization code can be exchanged for tokens by sending it to the token endpoint (see next section).
## Token
The token endpoint returns tokens given valid grants. This grant is either an authorization code retrieved from the authorize endpoint or a refresh token. In thee case of refresh token, the token endpoint is also capable of revoking a token.
All interactions with this endpoint need to be HTTP POST requests to `http://your-instance.com/auth/token` with the request body encoded in `application/x-www-form-urlencoded`.
### Authorization code
> All requests to the token endpoint need to contain the exact same client ID as was used to redirect the user to the authorize endpoint.
Use the grant type `authorization_code` to retrieve the tokens after a user has successfully finished the authorize step. The request body is:
```
grant_type=authorization_code&
code=12345&
client_id=https%3A%2F%2Fhass-auth-demo.glitch.me
```
The return response will be an access and refresh token:
```json
{
"access_token": "ABCDEFGH",
"expires_in": 1800,
"refresh_token": "IJKLMNOPQRST",
"token_type": "Bearer"
}
```
The access token is a short lived token that can be used to access the API. The refresh token can be used to fetch new access tokens. The `expires_in` value is seconds that the access token is valid.
An HTTP status code of 400 will be returned if an invalid request has been issued. The HTTP status code will be 403 if a token is requested for an inactive user.
```json
{
"error": "invalid_request",
"error_description": "Invalid client id",
}
```
### Refresh token
Once you have retrieved a refresh token via the grant type `authorization_code`, you can use it to fetch new access tokens. The request body is:
```
grant_type=refresh_token&
refresh_token=IJKLMNOPQRST&
client_id=https%3A%2F%2Fhass-auth-demo.glitch.me
```
The return response will be an access token:
```json
{
"access_token": "ABCDEFGH",
"expires_in": 1800,
"token_type": "Bearer"
}
```
An HTTP status code of 400 will be returned if an invalid request has been issued.
```json
{
"error": "invalid_request",
"error_description": "Invalid client id",
}
```
### Revoking a refresh token
> client_id is not need for revoke refresh token
The token endpoint is also capable of revoking a refresh token. Revoking a refresh token will immediately revoke the refresh token and all access tokens that it has ever granted. To revoke a refresh token, make the following request:
```
token=IJKLMNOPQRST&
action=revoke
```
The request will always respond with an empty body and HTTP status 200, regardless if the request was successful.
## Long-lived access token
A long-lived access token is usually used for 3rd party API calls and webhook-ish integrations. To generate a long-lived access token, an active websocket connection has to be established.
Send websocket command `auth/long_lived_access_token` will create a long-lived access token for current user. Access token will not be saved in Home Assistant. User need to record the token in secure place.
```json
{
"id": 11,
"type": "auth/long_lived_access_token",
"client_name": "GPS Logger",
"client_icon": null,
"lifespan": 365
}
```
Result will be a long-lived access token:
```json
{
"id": 11,
"type": "result",
"success": true,
"result": "ABCDEFGH"
}
```
Additionally, a long-lived access token can be created using the UI tool located at the bottom of the user's Home Assistant profile page.
## Making authenticated requests
Once you have an access token, you can make authenticated requests to the Home Assistant APIs.
For the websocket connection, pass the access token in the [authentication message](https://developers.home-assistant.io/docs/en/external_api_websocket.html#authentication-phase).
For HTTP requests, pass the token type and access token as the authorization header:
```
Authorization: Bearer ABCDEFGH
```
### Example: cURL
```shell
curl -X GET \
https://your.awesome.home/api/error/all \
-H 'Authorization: Bearer ABCDEFGH'
```
### Example: Python
```python
import requests
url = "https://your.awesome.home/api/error/all"
headers = {
'Authorization': "Bearer ABCDEFGH",
}
response = requests.request('GET', url, headers=headers)
print(response.text)
```
### Example: NodeJS
```JavaScript
fetch('https://your.awesome.home/api/error/all', {
headers: { Authorization: 'Bearer ABCDEFGH' }
}).then(function (response) {
if (!response.ok) {
return Promise.reject(response);
}
return response.text();
}).then(function (body ) {
console.log(body);
});
```
If the access token is no longer valid, you will get a response with HTTP status code 401 unauthorized. This means that you will need to refresh the token. If the refresh token doesn't work, the tokens are no longer valid and so the user is no longer logged in. You should clear the user's data and ask the user to authorize again.
[oauth2-spec]: https://tools.ietf.org/html/rfc6749
[indieauth-spec]: https://indieauth.spec.indieweb.org/
[indieauth-clients]: https://indieauth.spec.indieweb.org/#client-identifier
## Signed paths
Sometimes you want a user to make a GET request to Home Assistant to download data. In this case the normal auth system won't do, as we can't link the user to an API with the auth header attached to it. In that case, a signed path can help.
A signed path is a normal path on our server, like `/api/states`, but with an attached secure authentication signature. The user is able to navigate to this path and will be authorised as the access token that created the signed path. Signed paths can be created via the websocket connection and are meant to be shortlived. The default expiration is 30 seconds.
To get a signed path, send the following command:
```js
{
"type": "auth/sign_path",
"path": "/api/states",
// optional, expiration time in seconds. Defaults to 30 seconds
"expires": 20
}
```
The response will contain the signed path:
```js
{
"path": "/api/states?authSig=ABCDEFGH"
}
```
Some things to note about a signed path:
- If the refresh token is deleted, the signed url is no longer valid.
- If the user is deleted, the signed url is no longer valid (because the refresh token will be deleted).
- If Home Assistant is restarted, the signed url is no longer valid.
- Access is only validated when the request is received. If a response takes longer than the expiration time (ie, downloading a large file), the download will continue after the expiration date has passed.

View File

@ -0,0 +1,74 @@
---
title: Server-sent events
id: version-0.83.0-external_api_server_sent_events
original_id: external_api_server_sent_events
---
The [server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events) feature is a one-way channel from your Home Assistant server to a client which is acting as a consumer. For a bi-directional streaming API, check out the [WebSocket API](external_api_websocket.md).
The URI that is generating the data is `/api/stream`.
A requirement on the client-side is existing support for the [EventSource](https://developer.mozilla.org/en-US/docs/Web/API/EventSource) interface.
There are various ways to access the stream. If you have not set an `api_password` in the [`http`](https://www.home-assistant.io/components/http/) section of your `configuration.yaml` file then you use your modern browser to read the messages. A command-line option is `curl`:
```bash
$ curl -X GET -H 'Authorization: Bearer ABCDEFGH' \
-H "Content-Type: application/json" http://localhost:8123/api/stream
```
> Will no longer work with the new Authentication system.
You can create a convenient view for this by creating an HTML file (`sse.html`) in the `www` folder of your Home Assistant configuration directory (`.homeassistant`). Paste this snippet into the file:
```html
<!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 'Authorization:Bearer ABCDEFGH' content-type:application/json
```
### Website
> Will no longer work with the new Authentication system.
The [home-assistant-sse](https://github.com/fabaff/home-assistant-sse) repository contains a more advanced example.
### Python
If you want to test the server-sent events without creating a website, the Python module [`sseclient` ](https://pypi.python.org/pypi/sseclient/) can help. To install (assuming Python and pip3 are already installed):
```bash
$ pip3 install sseclient
```
A simple script to consume SSE in Python looks like this:
```python
from sseclient import SSEClient
auth = {'Authorization': 'Bearer ABCDEFGH'}
messages = SSEClient('http://localhost:8123/api/stream', headers=auth)
for msg in messages:
print(msg)
```

View File

@ -0,0 +1,48 @@
---
title: Presenting your add-on
id: version-0.83.0-hassio_addon_presentation
original_id: hassio_addon_presentation
---
If you decide to share your add-on to the public, paying attention to details is recommended. Of course, your add-on should have a proper name and description, but Hass.io also gives you some other tools to present your add-on even nicer.
## Adding documentation
Good documentation helps the consumer of your add-on to understand its usage, explains configuration options, points users in the right direction in the case they have questions or issues, and contains the license under which the add-on was published.
This file containing the documentation is usually referred to as the "README", which is generally published as the `README.md` file.
Take a look at other projects for inspiration. For example, see the `README.md` of the [Community Hass.io Add-ons: Homebridge](https://github.com/hassio-addons/addon-homebridge/blob/master/README.md) add-on.
In future versions of Hass.io, the `README.md` file will be displayed in the Home Assistant frontend.
## Add-on icon & logo
A picture is worth a thousand words. Therefore, your add-on can be improved by adding a proper image icon and logo. Those images are used when showing your add-on in the Home Assistant Hass.io panel and which will significantly improve the visual representation of your add-on.
Requirements for the logo of your add-on:
- The logo must be in the Portable Network Graphics format (`.png`).
- The filename must be `logo.png`.
- It is recommended to keep the logo size around 250x100px. You may choose to use a different size or aspect ratio as you seem fit for your add-on.
Requirements for the icon of your add-on:
- The icon must be in the Portable Network Graphics format (`.png`).
- The filename must be `icon.png`.
- The aspect ratio of the icon must be 1x1 (square).
- It is recommended to use an icon size of 128x128px.
## Keeping a changelog
It is likely you are going to release newer versions of your add-on in the future. In case that happens, the users of your add-on would see an upgrade notice and probably want to know what changes were made in the latest version.
A changelog is a file which contains a curated, chronologically ordered list of notable changes for each version of your add-on and is generally published as the `CHANGELOG.md` file.
If you are in need of a guide on keeping a changelog, we would recommend checking the [keep a changelog](http://keepachangelog.com) website. They have developed a standard that is used by many opensource projects around the world.
In future versions of Hass.io, the `CHANGELOG.md` file will be displayed in the Home Assistant frontend.
## AppArmor
You can use own security profile for you Add-on with AppArmor. Default it is enabled and use the Docker default profile. Put `apparmor.txt` file into your Add-on folder and it will load this file as primary profile. Use the config options to set the name of that profile.

View File

@ -0,0 +1,60 @@
---
title: Publishing your add-on
id: version-0.83.0-hassio_addon_publishing
original_id: hassio_addon_publishing
---
There are two different ways of publishing add-ons. One is to publish pre-build containers to Docker Hub and the other option is to have users build the containers locally on their Hass.io instance.
#### Pre-build containers
With pre-build containers, the developer is responsible for building the images for each architecture on their machine and push the results out to Docker Hub. This has a lot of advantages for the user. As a user it will only have to download the final container and be up and running once the download finishes. This makes the installation process fast and almost no chance of failure. This is the preferred method.
We have automated the process of building and publishing add-ons. See below for the instructions.
#### Locally build containers
Starting Hass.io 0.26, it is possible to distribute add-ons that will be built on the users machine. The advantage is that as a developer it is easy to test an idea and see if people are interested in your add-ons. This method includes installing and potentially compiling code. This means that installing such an add-on is slow and adds more wear and tear to users SD card/hard drive than the above mentioned pre-build solution. It also has a higher chance of failure if one of the dependencies of the container has changed or is no longer available.
Use this option when you are playing with add-ons and seeing if someone is interested in your work. Once you're an established repository, please migrate to pushing builds to Docker Hub as it greatly improves the user experience. In the future we will mark locally built add-ons in the add-on store to warn users.
## Build scripts to publish add-ons to Docker Hub
All add-ons are simple docker containers. Inside your add-on `config.json` you specify the Docker image that will be installed for your add-on:
```json
{
...
"image": "myhub/image-{arch}-addon-name",
...
}
```
You can use `{arch}` inside the image name to support multiple architectures with one (1) configuration file. It will be replaced with the architecture of the user when we load the image. If you use `Buildargs` you can use the `build.json` to overwrite our default args.
Hass.io assumes that the `master` branch of your add-on repository matches the latest tag on Docker Hub. When you're building a new version, it's suggested that you use another branch, ie `build` or do it with a PR on GitHub. After you push the add-on to [Docker Hub](https://hub.docker.com/), you can merge this branch to master.
## Custom Add-ons
You need a Docker Hub account to make your own add-ons. You can build your Docker images with the Docker `build` command or use our script that make it simple. Pull our [Builder Docker engine][builder] and run one of the following commands.
For a git repository:
```bash
$ docker run --rm --privileged -v \
~/.docker:/root/.docker homeassistant/amd64-builder \
--all -t addon-folder -r https://github.com/xy/addons \
-b branchname
```
For a local repository:
```bash
$ docker run --rm --privileged -v \
~/.docker:/root/.docker -v /my_addon:/data homeassistant/amd64-builder \
--all -t /data
```
> If you are developing on macOS and using Docker for Mac, you may encounter an error message similar to the following: <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

View File

@ -0,0 +1,168 @@
{
"version-0.83.0-Architecture": {
"Architecture": [
"version-0.83.0-architecture_index",
"version-0.83.0-architecture_components",
"version-0.83.0-architecture_entities",
"version-0.83.0-architecture_hassio"
],
"Entities": [
"version-0.83.0-entity_index",
"version-0.83.0-entity_alarm_control_panel",
"version-0.83.0-entity_binary_sensor",
"version-0.83.0-entity_climate",
"version-0.83.0-entity_cover",
"version-0.83.0-entity_fan",
"version-0.83.0-entity_light",
"version-0.83.0-entity_lock",
"version-0.83.0-entity_media_player",
"version-0.83.0-entity_remote",
"version-0.83.0-entity_sensor",
"version-0.83.0-entity_switch",
"version-0.83.0-entity_vacuum",
"version-0.83.0-entity_water_heater",
"version-0.83.0-entity_weather"
],
"Authentication": [
"version-0.83.0-auth_index",
"version-0.83.0-auth_permissions",
"version-0.83.0-auth_api",
"version-0.83.0-auth_auth_provider",
"version-0.83.0-auth_auth_module"
],
"Configuration.yaml": [
"version-0.83.0-configuration_yaml_index"
],
"Config Entries": [
"version-0.83.0-config_entries_index",
"version-0.83.0-config_entries_config_flow_handler"
],
"Data Entry Flow": [
"version-0.83.0-data_entry_flow_index"
],
"Entity Registry": [
"version-0.83.0-entity_registry_index"
],
"Device Registry": [
"version-0.83.0-device_registry_index"
]
},
"version-0.83.0-Extending Frontend": {
"Frontend": [
"version-0.83.0-frontend_index",
"version-0.83.0-frontend_architecture",
"version-0.83.0-frontend_development",
"version-0.83.0-frontend_data",
"version-0.83.0-frontend_external_auth"
],
"Extending the frontend": [
"version-0.83.0-frontend_add_card",
"version-0.83.0-frontend_add_more_info",
"version-0.83.0-frontend_add_websocket_api"
],
"Custom UI": [
"version-0.83.0-lovelace_custom_card",
"version-0.83.0-frontend_creating_custom_ui",
"version-0.83.0-frontend_creating_custom_panels"
]
},
"version-0.83.0-Extending HASS": {
"Developing a feature": [
"version-0.83.0-development_index",
"version-0.83.0-development_environment",
"version-0.83.0-development_submitting",
"version-0.83.0-development_checklist",
"version-0.83.0-development_guidelines",
"version-0.83.0-development_testing",
"version-0.83.0-development_catching_up",
"version-0.83.0-development_validation",
"version-0.83.0-development_typing"
],
"Development 101": [
"version-0.83.0-dev_101_index",
"version-0.83.0-dev_101_hass",
"version-0.83.0-dev_101_events",
"version-0.83.0-dev_101_states",
"version-0.83.0-dev_101_services",
"version-0.83.0-dev_101_config"
],
"Integration Quality Scale": [
"version-0.83.0-integration_quality_scale_index"
],
"Creating Platforms": [
"version-0.83.0-creating_platform_index",
"version-0.83.0-creating_platform_code_review",
"version-0.83.0-creating_platform_example_light",
"version-0.83.0-creating_platform_example_sensor"
],
"Creating Components": [
"version-0.83.0-creating_component_index",
"version-0.83.0-creating_component_code_review",
"version-0.83.0-creating_component_deps_and_reqs",
"version-0.83.0-creating_component_events",
"version-0.83.0-creating_component_states",
"version-0.83.0-creating_component_discovery",
"version-0.83.0-creating_component_loading",
"version-0.83.0-creating_component_generic_discovery"
]
},
"version-0.83.0-Misc": {
"Introduction": [
"version-0.83.0-misc"
],
"External API": [
"version-0.83.0-external_api_rest",
"version-0.83.0-external_api_websocket",
"version-0.83.0-external_api_server_sent_events"
],
"Internationalization": [
"version-0.83.0-internationalization_index",
"version-0.83.0-internationalization_backend_localization",
"version-0.83.0-internationalization_custom_component_localization",
"version-0.83.0-internationalization_translation"
],
"Documentation": [
"version-0.83.0-documentation_index",
"version-0.83.0-documentation_standards",
"version-0.83.0-documentation_create_page"
],
"Intents": [
"version-0.83.0-intent_index",
"version-0.83.0-intent_firing",
"version-0.83.0-intent_handling",
"version-0.83.0-intent_conversation",
"version-0.83.0-intent_builtin"
],
"Native App Integration": [
"version-0.83.0-app_integration_index",
"version-0.83.0-app_integration_setup",
"version-0.83.0-app_integration_sending_data",
"version-0.83.0-app_integration_webview"
],
"asyncio": [
"version-0.83.0-asyncio_index",
"version-0.83.0-asyncio_101",
"version-0.83.0-asyncio_categorizing_functions",
"version-0.83.0-asyncio_working_with_async"
],
"Hass.io": [
"version-0.83.0-hassio_debugging",
"version-0.83.0-hassio_hass"
],
"Hass.io Add-Ons": [
"version-0.83.0-hassio_addon_index",
"version-0.83.0-hassio_addon_tutorial",
"version-0.83.0-hassio_addon_config",
"version-0.83.0-hassio_addon_communication",
"version-0.83.0-hassio_addon_testing",
"version-0.83.0-hassio_addon_publishing",
"version-0.83.0-hassio_addon_presentation",
"version-0.83.0-hassio_addon_repository",
"version-0.83.0-hassio_addon_security"
],
"Maintainer docs": [
"version-0.83.0-maintenance",
"version-0.83.0-releasing"
]
}
}

View File

@ -1,4 +1,5 @@
[
"0.83.0",
"0.82.0",
"0.81.0",
"0.80.0",