Skip to main content

External bus

The frontend is able to set up a message bus with an external app that is embedding the Home Assistant frontend. This system is a generalization of the external authentication, making it easier to add more commands in the future without extensive plumbing on either the app or frontend side.

Message exchange

Just like external auth, message exchange is achieved by the external app making a JavaScript method available.

Messages are passed to the external app as serialized JSON objects. The function that will be called takes a single parameter: a string. The external app will have to process the message and deal with it accordingly (or ignore it).

On Android, your app needs to define the following method:

window.externalApp.externalBus(message: string)

On iOS, your app needs to define the following method:

window.webkit.messageHandlers.externalBus.postMessage(message: string);

To send messages to the frontend, serialize your message to JSON and call the following function from the external app:

window.externalBus(message: string)

Message format

The message describes an action or a piece of information that the sender wants the receiver to do or know about. If it's an action, the sender will expect a response with the result of that action. A response to a command can either be successful or failed.

Action and info message format

The format of a message that contains or provides information is the same. It contains an identifier, a type and an optional payload (depending on the type).

A result message will re-use the identifier in the response, to indicate to which action the response is related.

The basic format of a message is the following:

{
id: number;
type: string;
payload?: unknown;
}

An example message:

{
"id": 5,
"type": "config/get"
}

Result message format

If the message was an action, the sender will expect a response with the result. The response is either success or failure.

The type of result depends on the type of the message that it is responding to. For example, if it is responding to config/get, the result should be an object describing the configuration.

Message formats:

interface SuccessResult {
id: number;
type: "result";
success: true;
result: unknown;
}

interface ErrorResult {
id: number;
type: "result";
success: false;
error: {
code: string;
message: string;
};
}

Supported messages

Get external config

Available in: Home Assistant 0.92 Type: config/get Direction: frontend to external app. Expects answer: yes

Query the external app for the external configuration. The external configuration is used to customize the experience in the frontend.

Expected response payload:

{
hasSettingsScreen: boolean;
canWriteTag: boolean;
}
  • hasSettingsScreen set to true if the external app will show a configuration screen when it receives the command config_screen/show. If so, a new option will be added to the sidebar to trigger the configuration screen.
  • canWriteTag set to true if the external app is able to write tags and so can support the tag/write command.

Show config screen config_screen/show

Available in: Home Assistant 0.92 Type: config_screen/show Direction: frontend to external app. Expect answer: no

Show the configuration screen of the external app.

Connection status update connection-status

Available in: Home Assistant 0.92 Type: connection-status Direction: frontend to external app. Expect answer: no

Notify the external app if the frontend is connected to Home Assistant.

Payload structure:

{
event: "connected" | "auth-invalid" | "disconnected";
}

Trigger haptic haptic

Available in: Home Assistant 0.92 Type: haptic Direction: frontend to external app. Expect answer: no

Notify the external app to trigger haptic feedback.

Payload structure:

{
hapticType:
| "success"
| "warning"
| "failure"
| "light"
| "medium"
| "heavy"
| "selection";

}

Write tag tag/write

Available in: Home Assistant 0.115 Type: tag/write Direction: frontend to external app Expect answer: yes

Tell the external app to open the UI to write to a tag. Name is the name of the tag as entered by the user. The name is null if no name has been set.

{
tag: string;
name: string | null;
}

Expected response payload is an empty object for now. We might add more later:

{}