This commit is contained in:
Paulus Schoutsen 2019-08-07 14:35:14 -07:00
parent b8677040ae
commit 8936f10fb3
4 changed files with 582 additions and 0 deletions

View File

@ -1570,6 +1570,13 @@
},
"version-0.96.0/version-0.96.0-hassio_addon_config": {
"title": "Add-On Configuration"
},
"version-0.97.0/version-0.97.0-creating_integration_manifest": {
"title": "Integration Manifest",
"sidebar_label": "Manifest"
},
"version-0.97.0/version-0.97.0-external_api_websocket": {
"title": "WebSocket API"
}
},
"links": {

View File

@ -0,0 +1,137 @@
---
title: Integration Manifest
sidebar_label: Manifest
id: version-0.97.0-creating_integration_manifest
original_id: creating_integration_manifest
---
Since 0.92.0, every integration has a manifest file to specify basic information about an integration. This file is stored as `manifest.json` in your integration directory. It is required to add such a file, except for custom components.
```json
{
"domain": "hue",
"name": "Philips Hue",
"documentation": "https://www.home-assistant.io/components/hue",
"dependencies": ["mqtt"],
"codeowners": ["@balloob"],
"requirements": ["aiohue==1.9.1"]
}
```
Or a minimal example that you can copy into your project:
```json
{
"domain": "your_domain_name",
"name": "Your Integration",
"documentation": "https://www.example.com",
"dependencies": [],
"codeowners": [],
"requirements": []
}
```
## Domain
The domain is a short name consisting of characters and underscores. This domain has to be unique and cannot be changed. Example of the domain for the mobile app integration: `mobile_app`.
## Name
The name of the integration.
## Documentation
The website containing documentation on how to use your integration. If this integration is being submitted for inclusion in Home Assistant, it should be `https://www.home-assistant.io/components/<domain>`
## Dependencies
Dependencies are other Home Assistant integrations that you want Home Assistant to set up successfully prior to the integration being loaded. This can be necessary in case you want to offer functionality from that other integration, like using webhooks or an MQTT connection.
## Code Owners
GitHub usernames or team names of people that are responsible for this integration. You should add at least your GitHub username here, as well as anyone who helped you to write code that is being included.
## Config Flow
Specify the `config_flow` key if your integration has a config flow to create a config entry. When specified, the file `config_flow.py` needs to exist in your integration.
```json5
{
"config_flow": true
}
```
## 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 are running in a virtual environment. This will make sure that all requirements are present at startup. If steps fail, like missing packages for the compilation of a module or other install errors, the component will fail to load.
Requirements is an array of strings. Each entry is a `pip` compatible string. For example, the media player Cast platform depends on the Python package PyChromecast v3.2.0: `["pychromecast==3.2.0"]`.
### Custom requirements during development & testing
During the development of a component, it can be useful to test against different versions of a requirement. This can be done in two steps, using `pychromecast` as an example:
```bash
pip install pychromecast==3.2.0 --target ~/.homeassistant/deps
hass --skip-pip
```
This will use the specified version, and prevent Home Assistant from trying to override it with what is specified in `requirements`.
If you need to make changes to a requirement to support your component, it's also possible to install a development version of the requirement using `pip install -e`:
```bash
git clone https://github.com/balloob/pychromecast.git
pip install -e ./pychromecast
hass --skip-pip
```
## Zeroconf
If your integration supports discovery via [Zeroconf](https://en.wikipedia.org/wiki/Zero-configuration_networking), you can add the type to your manifest. If the user has the `zeroconf` integration loaded, it will load the `zeroconf` step of your integration's config flow when it is discovered.
```json5
{
"zeroconf": ["_googlecast._tcp.local."]
}
```
## SSDP
If your integration supports discovery via [SSDP](https://en.wikipedia.org/wiki/Simple_Service_Discovery_Protocol), you can add the type to your manifest. If the user has the `ssdp` integration loaded, it will load the `ssdp` step of your integration's config flow when it is discovered. We support SSDP discovery by ST, manufacturer and device type. Your integration is discovered if any of the specified info is found. It's up to your config flow to filter out duplicates.
```json5
{
"ssdp": {
"st": [
"roku:ecp"
],
"manufacturer": [
"Roku"
],
"device_type": [
"urn:roku-com:device:player:1-0"
]
}
}
```
## HomeKit
If your integration supports discovery via HomeKit, you can add the supported model names to your manifest. If the user has the `zeroconf` integration loaded, it will load the `homekit` step of your integration's config flow when it is discovered.
HomeKit discovery works by testing if the discovered modelname starts with any of the model names specified in the manifest.json.
```json5
{
"homekit": {
"models": [
"LIFX"
]
}
}
```
Discovery via HomeKit does not mean that you have to talk the HomeKit protocol to communicate with your device. You can communicate with the device however you see fit.
When a discovery info is routed to your integration because of this entry in your manifest, the discovery info is no longer routed to integrations that listen to the HomeKit zeroconf type.

View File

@ -0,0 +1,437 @@
---
title: WebSocket API
id: version-0.97.0-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 WebSockets. Implementations in different languages:
- [JavaScript](https://github.com/home-assistant/home-assistant-js-websocket) - powers the frontend
- [Python](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket-client.py) - CLI client using [`asyncws`](https://async-websockets.readthedocs.io/en/latest/)
- [JavaScript/HTML](https://raw.githubusercontent.com/home-assistant/home-assistant-dev-helper/master/ha-websocket.html) - WebSocket connection in your browser
Connect your websocket implementation to `ws://localhost:8123/api/websocket`. You will need a valid access token.
If you are not using the [`frontend`](https://www.home-assistant.io/components/frontend/) in your setup then you need to add the [`websocket_api` component](https://www.home-assistant.io/components/websocket_api/) to your `configuration.yaml` file to use the WebSocket API.
## Server states
1. Client connects.
1. Authentication phase starts.
- Server sends `auth_required` message.
- Client sends `auth` message.
- If `auth` message correct: go to 3.
- Server sends `auth_invalid`. Go to 6.
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",
"access_token": "ABCDEFGHIJKLMNOPQ"
}
```
```json
{
"id": 5,
"type":"event",
"event":{
"data":{},
"event_type":"test_event",
"time_fired":"2016-11-26T01:37:24.265429+00:00",
"origin":"LOCAL"
}
}
```
## Authentication phase
When a client connects to the server, the server will test if the client is authenticated. Authentication will not be necessary if no api_password is set or if the user fulfills one of the other criteria for authentication (trusted network, password in url/header).
If no authentication is needed, the authentication phase will complete and the server will send an `auth_ok` message.
```json
{
"type": "auth_ok"
}
```
If authentication is necessary, the server sends out `auth_required`.
```json
{
"type": "auth_required"
}
```
This means that the next message from the client should be an auth message. You can authorize with an access token.
```json
{
"type": "auth",
"access_token": "ABCDEFGH"
}
```
For now, we also support authentication with an API password (legacy auth).
```json
{
"type": "auth",
"api_password": "supersecret"
}
```
If the client supplies valid authentication, the authentication phase will complete by the server sending the `auth_ok` message:
```json
{
"type": "auth_ok"
}
```
If the data is incorrect, the server will reply with `auth_invalid` message and disconnect the session.
```json
{
"type": "auth_invalid",
"message": "Invalid password"
}
```
## Command phase
During this phase the client can give commands to the server. The server will respond to each command with a `result` message indicating when the command is done and if it was successful.
```json
{
"id": 6,
"type": "result",
"success": true,
// Can contain extra result info
"result": null
}
```
## Subscribe to events
The command `subscribe_events` will subscribe your client to the event bus. You can either listen to all events or to a specific event type. If you want to listen to multiple event types, you will have to send multiple `subscribe_events` commands.
```json
{
"id": 18,
"type": "subscribe_events",
// Optional
"event_type": "state_changed"
}
```
The server will respond with a result message to indicate that the subscription is active.
```json
{
"id": 18,
"type": "result",
"success": true,
"result": null
}
```
For each event that matches, the server will send a message of type `event`. The `id` in the message will point at the original `id` of the `listen_event` command.
```json
{
"id": 18,
"type":"event",
"event":{
"data":{
"entity_id":"light.bed_light",
"new_state":{
"entity_id":"light.bed_light",
"last_changed":"2016-11-26T01:37:24.265390+00:00",
"state":"on",
"attributes":{
"rgb_color":[
254,
208,
0
],
"color_temp":380,
"supported_features":147,
"xy_color":[
0.5,
0.5
],
"brightness":180,
"white_value":200,
"friendly_name":"Bed Light"
},
"last_updated":"2016-11-26T01:37:24.265390+00:00"
},
"old_state":{
"entity_id":"light.bed_light",
"last_changed":"2016-11-26T01:37:10.466994+00:00",
"state":"off",
"attributes":{
"supported_features":147,
"friendly_name":"Bed Light"
},
"last_updated":"2016-11-26T01:37:10.466994+00:00"
}
},
"event_type":"state_changed",
"time_fired":"2016-11-26T01:37:24.265429+00:00",
"origin":"LOCAL"
}
}
```
### Unsubscribing from events
You can unsubscribe from previously created subscription events. Pass the id of the original subscription command as value to the subscription field.
```json
{
"id": 19,
"type": "unsubscribe_events",
"subscription": 18
}
```
The server will respond with a result message to indicate that unsubscribing was successful.
```json
{
"id": 19,
"type": "result",
"success": true,
"result": null
}
```
## Calling a service
This will call a service in Home Assistant. Right now there is no return value. The client can listen to `state_changed` events if it is interested in changed entities as a result of a service call.
```json
{
"id": 24,
"type": "call_service",
"domain": "light",
"service": "turn_on",
// Optional
"service_data": {
"entity_id": "light.kitchen"
}
}
```
The server will indicate with a message indicating that the service is done executing.
```json
{
"id": 24,
"type": "result",
"success": true,
"result": null
}
```
## Fetching states
This will get a dump of all the current states in Home Assistant.
```json
{
"id": 19,
"type": "get_states"
}
```
The server will respond with a result message containing the states.
```json
{
"id": 19,
"type": "result",
"success": true,
"result": [ ... ]
}
```
## Fetching config
This will get a dump of the current config in Home Assistant.
```json
{
"id": 19,
"type": "get_config"
}
```
The server will respond with a result message containing the config.
```json
{
"id": 19,
"type": "result",
"success": true,
"result": { ... }
}
```
## Fetching services
This will get a dump of the current services in Home Assistant.
```json
{
"id": 19,
"type": "get_services"
}
```
The server will respond with a result message containing the services.
```json
{
"id": 19,
"type": "result",
"success": true,
"result": { ... }
}
```
## Fetching panels
This will get a dump of the current registered panels in Home Assistant.
```json
{
"id": 19,
"type": "get_panels"
}
```
The server will respond with a result message containing the current registered panels.
```json
{
"id": 19,
"type": "result",
"success": true,
"result": [ ... ]
}
```
## Fetching camera thumbnails
_Introduced in Home Assistant 0.69._
Return a b64 encoded thumbnail of a camera entity.
```json
{
"id": 19,
"type": "camera_thumbnail",
"entity_id": "camera.driveway"
}
```
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>"
}
}
```
## Pings and Pongs
The API supports receiving a ping from the client and returning a pong. This serves as a heartbeat to ensure the connection is still alive:
```json
{
"id": 19,
"type": "ping"
}
```
The server must send a pong back as quickly as possible, if the connection is still active:
```json
{
"id": 19,
"type": "pong"
}
```
## Error handling
If an error occurs, the `success` key in the `result` message will be set to `false`. It will contain an `error` key containing an object with two keys: `code` and `message`.
| Code | Description |
| ----- | ------------ |
| 1 | A non-increasing identifier has been supplied.
| 2 | Received message is not in expected format (voluptuous validation error).
| 3 | Requested item cannot be found
```json
{
"id": 12,
"type":"result",
"success": false,
"error": {
"code": 2,
"message": "Message incorrectly formatted: expected str for dictionary value @ data['event_type']. Got 100"
}
}
```

View File

@ -1,4 +1,5 @@
[
"0.97.0",
"0.96.0",
"0.95.0",
"0.94.0",